I understand that syntax may be more convenient for some, but this is indirection, and is a source of complexity that may impede collaboration from other devs more familiar with JavaScript.
I understand that syntax may be more convenient for some, but this is indirection, and is a source of complexity that may impede collaboration from other devs more familiar with JavaScript.
In fact, Brendan Eich has taken a bunch of it's features and they will be included in the next version of JS (woot!): http://brendaneich.com/2011/01/harmony-of-my-dreams/
Every single time you see JavaScript prototypes used effectively, you'll find that they follow a classical pattern: A constructor function serves as the class object from which new objects are instantiated. Syntax like instanceof ("object instanceof class") gives this away. So do all of the built-in JavaScript classes: String, Function, RegExp, Number...
If it's an abstract object that defines common properties for instances, it's a class object, regardless of what you choose to call it. JS prototypes just expose the implementation mechanism, and CoffeeScript just provides you with a convenient way to manipulate the prototype chain.
* In js->cs rewrites I usually wind up cutting the line count in half, but most of that is eliminating all the stray closing brackets on their own lines and collapsing if statements into single lines.
One particular example that changed everything for me was the natural and simple way I could build the typical callback constructs with -> and => , so they almost look like blocks in ruby, and feel way more natural as a control construct, and I didnt have to stack lots of })}); and so on.
If you're rather new to something, the ease of use and the simplicity and readability speeden up the learning process extremely.
That being said, there are also a couple of things in cs that are kind of silly.. like using 'for i in my_array', but 'for k of my_dict', and stuff like that, that are really hard to debug.
Although, in terms of debugging, the fact that it gets compiled and possible errors are early detected and a canonical js is generated also saved me lot of time, in particular with IE ;-)
"for item in list" vs "for key, value of object" is an unfortunate necessary evil. It would be great to use the same keyword, "in", for both types of loop, but I'm afraid there's no way for us to know at compile time if "list" or "object" is really an array, or really an object.
for (var i = 0, l = list.length; i < l; i++) { ... }
And objects iterated over with: for (var key in object) { ... }
Using a "for-in" loop over a JS array isn't acceptable, for performance and semantics reasons, and neither is sniffing at runtime to determine whether the object passed is an array, or an object.Ideally, JavaScript would have supported a single iteration protocol for both arrays and objects from the get-go, but alas...
If you dont mind my asking, how would i go about using CoffeeScript with Node?
If it's more elaborated, you might want to set up some kind of build process and then use the generated js files. You could use a simple Makefile and compile your coffee files with coffee -c -b.
Add to this the fact that JavaScript's prototype system isn't actually very flexible, and you're almost always better off to roll a class-based system on top of it.
A function that does nothing useful but illustrates some pain points:
function frob(obj) {
var rest = [].slice.call(arguments, 1)
, results = []
for (var k in obj) if (obj.hasOwnProperty(k)) {
v = obj[k]
if (blurgh(v, rest)) {
results.push(v)
}
}
return results
}
This is roughly the same function in CS: frob = (obj, rest...) -> [v for v of obj if blurgh(v, rest)]
That's at least 5x more expressive. And it works in browsers, node, and pretty much every other JS environment. I don't write CS but you have to be blind to deny its benefits.edited: Fixed the CS to iterate over keys of obj using 'of' based on other comments here
Nitpicking aside, I totally agree about the expressiveness. I find myself writing about half the number of lines in CS as compared to JS, and the syntax fits my brain better.
frob = (obj, rest...) -> v for v of obj when blurgh(v, rest)
edit: parens dropped for noise reductionI'm wondering why I find this so annoying though. It's not like I complain about having to put parentheses in math to make sure stuff is evaluated with the precedence I want.
foo bar baz 2 # is foo(bar(baz(2)))
foo bar baz(), 2 # is foo(bar(baz(),2))
foo bar().baz 2 # is foo(bar().baz(2))
In every case, the foo is the last item on the line. In the second there's an argument after the call to baz() so it's not the last thing on the line and needs parens. In the third, baz is being chained off bar so bar is not the last thing on the line and needs parens. In general I'd do all the parens except maybe the ones for foo in the second and third cases simply because it takes a minute to figure out where the calls get split when you re-read the code.I tend to drop the call parens in situations the following:
# DSLish things
task 'foo', depends: ['bar']
# Callback/lambda taking things
xhr_get url, ->
stop_animation()
That actually covers a fairly wide set of use cases for me since I tend to write DSLish/callback code but for things like `add(2,2)` I write in the parens regardless of position.I disagree with this (though I agree with the rest of your post). The people that like CoffeeScript (and StratifiedJS and other projects like ObjectiveJ) are generally people that do get JavaScript really well. They just want to make it better.
The problem with CoffeeScript and the others is that they are not JavaScript. CoffeeScript is pretty straightforward in that it hardly even looks like JS and just compiles down to it, but others pretend to be JS but introduce new structures that make them all completely different languages (and do source transformation using JS in the browser).
If you don't know the transformations and you don't know JS very well, all these languages on top of JS will leave you stranded the second something goes wrong anywhere in the stack.
I'd like to see JS adopt some core structures for concurrency, namespaces and more CommonJS stuff instead of adding let, generators and comprehensions - which are nice, but mostly just fluff because you can do all those using the core language already and they're details nobody really cares about.
Personally I think Coffeescript is a big step forward. A pity it will likely never gain enough momentum to see native implementations on the major browsers.
JavaScript itself doesn't embrace a prototypal model. When was the last time you cloned an object to create a new one in JS?
JavaScript's model is much closer to classes than prototypes. The only real significant difference is that unlike class systems, JavaScript allows inheriting both "methods" and "state" from its "class". Otherwise, the language works more or less like a class-based one.
Sure, the name sucks, but that's hardly an issue.
Sure, as long as you already understand Javascript. Think of people who are learning, or middle managers that are hiring. It's a lot more of a thorn than you might think, because you're educated.BEATUY IS IN THE EYE OF THE BEHOLDER people! Just because you find javascript 'ugly' and coffeescript 'beautiful' doesn't actually mean everyone agrees with you. I think Javascript is beautiful and I've been coding it for 14 years. I have no need to replace the syntax, or complicate my development tools, or make debugging any more complicated that it already is.
Coffeescript evangelists are like born-agains who try to convert every man woman or child to their newfound religion because their god is the true god. It's annoying really.
It's that simple.