Poll: Have you moved from JavaScript to CoffeeScript?
Not sure why it wasn't an actual poll - maybe they don't have enough karma. Anyway, here is an actual poll. Feel free to comment as to reasons or other possibilities.
Not sure why it wasn't an actual poll - maybe they don't have enough karma. Anyway, here is an actual poll. Feel free to comment as to reasons or other possibilities.
It's heartening to see so many people responding to this poll. I hopped on the CoffeeScript bandwagon more than a year ago; a week of using it was enough to convince me to stop writing pure JS. It's become my favorite language, even overtaking Ruby. (Cue dhh at last month's RailsConf keynote: "Looking at CoffeeScript was the first time I got language envy.")
These last six months have been amazing: In December, CoffeeScript hit 1.0. In April, it officially became a part of Rails. In May, Jeremy Ashkenas gave a talk alongside Brendan Eich at JSConf. That same month, the beta of my book was PragProg's #1 direct seller.
So who knows what the next year holds for CoffeeScript? It's probably never going to take off in cubicle-land—and for that we should be grateful. But I would like to see it get more traction beyond the Ruby and Node.js worlds. (Pythonistas, represent!) And I'm sure we'll see far more high-profile projects written in it... and not just at 37signals.
For web developers, JavaScript is where the action is right now. And CoffeeScript is, in my opinion, the best way to write JavaScript.
Like most languages at 1.0, though, it has some growing to do. I still find myself needing to dive down into the compiled JavaScript to make sure it's doing what I think it's doing in some unclear situations (nested data structures we used in our tests, for example). I've seldom found a need to take similar actions in more mature languages and I'm sure that will improve as CoffeeScript development continues.
I warmly welcome any tool that makes my life as a developer easier or more enjoyable (CoffeeScript does both) and I hope its success continues to inspire the growth of client-side web development languages.
The benefits over straight JavaScript are amazing—I’d been writing careful code that drew from the ‘good parts’ mentality and pre-declared all variables, etc. Now I hardly ever have to worry about it.
As I continue to write Rails code I wish I could skip commas in hashes. I didn’t really have an opinion on significant whitespace before (only briefly played with Python) but now I love it. It’s also the first time I’ve used splats, and I was delighted by the brevity it can achieve in combination with the erb-esque interpolation: http://cl.ly/2b371b380g3j071E2g0h
The integration with docco has rewarded my habit of trying to write good documentation. I’ve tried to enforce a policy that any new CS must be documented.
https://bugzilla.mozilla.org/show_bug.cgi?id=618650
https://bugs.webkit.org/show_bug.cgi?id=30933
In the meantime, CoffeeScript tries to make debugging easy by compiling to straightforward, readable JS, with meaningful variable names, normal indentation, and all that. Patches to make the output clearer/cleaner for specific bits are always welcome.
http://jashkenas.github.com/coffee-script/#loops
To be clear, I think CoffeeScript is an impressive language/abstraction. I just get tired of people selling the Javascript output as always being "straightforward" and "readable".
The only difference from a "hand-written" loop is that you would use `i` and `ln` instead of `_i` and `_len`, and something in context like `numbers` instead of `_results`.
You're also overlooking the fact that this can be considered an advantage: variable naming for these transient uses is very consistent. When writing JS you could have names all over, even a different one for every loop.
var i, foods = ['toast', 'cheese', 'wine'], foods_length = foods.length;
for (i = 0; i < foods_length; i++) {
eat(food[i]);
}
Prefixing variables with an underscore is not an advantage in readability because it lends nothing to the description of what the variable represents. Its another glyph that you have to visually parse before reaching possible meaning.I said consistency is good. And you just proved my point.
alert(var one = 2);
In CoffeeScript, (nearly) everything is an expression. So you need to be able to do this: alert one = 2
By pushing up all the var declarations, all assignments can be themselves assigned, returned, or passed as arguments to function calls directly.Client-side is zero problem because the chrome and firebug developer tools jump you right to the line in the JS file, and you can figure out where the error is there since the compiled coffeescript is very readable.
Server-side has a slight hassle since there's no clickable link, so the line numbers don't help much, but a quick look at the stack trace makes it pretty easy to find where in the coffeescript its referring to.
Most of the problems we’ve dealt with have been due to using new syntax, figuring out when we need parentheses/how to pass anonymous functions, and so on.
Referring to the compiled output definitely helps, but we’re pretty familiar with JS at this point. Not sure how difficult it would be for those with less experience.
I can understand the syntax gripes that some people have towards Javascript but I think this has more to do with a Ruby notion of "elegance" coupled with a lack of familiarity with Javascript then it does with actual issues with Javascript. In fact, I prefer Javascript to Ruby.
I have gone the whole way with Prototype and then the whole way back. These days I prefer using just 20 or so functional DOM helpers rather than Prototype's Element extensions or JQuery's wrappers. A handful of DOM functions are significantly faster. As a result I have found it useful to keep third party dependencies to a minimum. A minimum of zero is working well for me so far. Writing raw Javascript is refreshing, even if it means a "prototype" here or there. I have written many "var" statements and have yet to see an undeclared variable pollute the global scope. I write for loops often. Sometimes I use forEach or reverse while loops. I don't seen any need for Coffeescript enumerators.
I keep checking up on Coffeescript from time to time but I prefer the explicit syntax of Javascript. After spending hours refactoring code the Rails way, I have come to prefer code that's big-O efficient, as fast as possible, as direct as possible, and if it takes a few lines less that's great.
Many folks rely on a "forEach" (or "each") iterator for all of their loops over arrays, because it's convenient. Unfortunately, it's also a very slow way to write an inner loop. CoffeeScript's comprehensions expand into regular JS loops over arrays and objects, so you get native speed, without the hassle. This:
for item in list
sum += item.amount
Compiles into this JavaScript: var item, _i, _len;
for (_i = 0, _len = list.length; _i < _len; _i++) {
item = list[_i];
sum += item.amount;
} for (var i = 0, ii = list.length; i < ii; i++) {
sum += list[i].amount;
}
Or: for (var i = 0, ii = list.length; i < ii; i++)
sum += list[i].amount;
There are ways to make normal JavaScript not look ugly ;)EDIT: fixed minor oversight
for i in [0...list.length] by 1
sum += list[i].amount
to get equivalent compiled output.I've used C and Java since high school, but I'm happy to be rid of that old `for` syntax. And I love that curly braces means only one thing in CoffeeScript: "I'm defining a new object with these key-value pairs."
Let me rewrite it for you: 1)
var list = [{amount:2}, {amount:5}], i, sum = 0;
for (i = 0; i < list.length; i++) { sum += list[i].amount; }
console.log(sum);
2) Or let's go even more simple...
var list = [{amount:2}, {amount:5}], i, sum = 0;
for (i in list) { sum += list[i].amount; }
Personally, i don't find anything difficult about that.. Actually looks incredibly simple. What are you actually saving by using Coffeescript...? Some brackets, parens and a semi-colon? I don't know, those are just second nature for me. I've never really stopped and thought, "wow, if only I didn't have to type these extra parens, this is really killing me..."
Not once.
The other "complexities" in the compiled JavaScript are there for perf reasons (not accessing the "length" properties in the condition portion of the for loop, for example).
Your comment underlies why some users find CoffeeScript useful in dealing with some of the idiosyncrasies and performance minutiae associated with JavaScript.
And I agree that accessing the length property in the conditional is not ideal.
I guess it comes down to this for me: I don't feel that Javascript has an unduly burdensome list of common idiosyncrasies to justify developing in a 'different language'/syntax that compiles into javascript and changing my development workflow to reap said questionably useful benefits.
Perhaps I am simply not the intended audience.
var sum=0,i=list.length; while(i--) sum += list[i].amount;
if it does: var sum=0,i=0,ln=list.length; while (ln-- && (sum += list[i++].amount));
but the for in syntax is nicer indeed.
I am used to writing native loops in Javascript, so taking your example I would usually write:
var length = list.length;
while (length--) sum += list[length].amount;
Here, the hand-tuned Javascript is 38% smaller than the compiled CoffeeScript, albeit a few more characters to type than the source CoffeeScript. The reverse while loop is also slightly faster to execute than the for loop in the compiled CoffeeScript.And I know that forEach loops incur additional overhead so I use them when it's convenient, when the arrays are small. I don't need to compile my Javascript just to keep from accidentally using forEach in situations where native loops would be better. I usually try to think about these things when I code and I enjoy being able to decide when to use a forEach loop, when to use a reverse while or a vanilla for loop etc. Sometimes, it's good to be specific in how you write code.
Furthermore, I would write for loops more succinctly than the compiled CoffeeScript in your example. You can use a for loop to declare the "item", "_i" and "_len" variables inside the loop itself without writing them twice. There's no need for the temporary item variable and the for loop is then short enough to be on one line:
for (var _i = 0, _len = list.length; _i < _len; _i++) sum += list[_i].amount;
Here, the hand-tuned Javascript is 32% smaller than the compiled CoffeeScript.I don't mind typing a few more characters if it means I can get closer to the code and serve smaller, faster code to users (or servers). If it means just one less deployment step, or one less 3rd party dependency, or one less leaky abstraction, it's worth it. I think this proves true in the cases above, where CoffeeScript certainly makes the compiled code longer, slower than it needs to be.
http://blog.directededge.com/2010/05/30/what-programming-lan...
The core message being: things like Scala, Erlang, et al still represent a tiny portion of the actual tech world. (And our customers tend to be biased towards being techy anyway.) Just because CoffeeScript gets a lot of mentions in the ultra-early-adopter demographic doesn't mean that it's measurably popular yet.
I guess at the end of the day syntax didn't end up being a killer feature that I needed. I still think CoffeeScript is awesome, but it doesn't solve problems that I can't already solve in JavaScript.
But two points:
1) The syntax wasn't the only thing that drew me to Ruby. 2) I just don't see an any real need morph my JS code into a similar syntax. Writing JS is pretty easy.
A quick way to port once: http://ricostacruz.com/js2coffee/
In terms of human-readable code, we reduced the lines of code by ~30%. It's cleaner and more concise. I feel our code is more managable because of CoffeeScript.
In terms of the generated JS, I really appreciate that CoffeeScript creates an abstraction that will implement JS best practices and consistency
At this point, any JS work I do is done with CoffeeScript
If you feel like providing any more color beyond your vote, your impressions after using CoffeeScript in anger -- I'd love to hear 'em.
BTW I love Backbone and Underscore and thanks to them (and also node) JS is actually more fun than ever.
I've played around with the editor at GitHub though and I really like how CoffeeScript reads. That being said, actually using it in the wild seems is road I'm not quite ready to cross yet.
What I'm doing is just using views as a way to provide some structure to what is currently a mess of jQuery event bindings and DOM manipulation. So instead of have a Backbone view that gets configured with a template and passed a model to render, I just do some setup code in the initialize function and then use Backbone's event function to setup all my event bindings for different DOM events that will occur within the element that is the root of that particular view.
This is working really well so far. It doesn't require completely rewriting the app to be a single-page client side heavy application, but does provide a significant amount of structure to the code making it much more manageable. It also lets me reuse some views (sort of like widgets) that were previously tied directly to specific elements in the DOM.
I'd like to see something like MileScript gain some traction--not to replace JavaScript, but as another tool in the toolbox. MileScript adds new value that you don't really get with plain JS; CoffeeScript doesn't.
Milescript turns Javascrpit into Java. Whilst many developers don't have a problem with static typing, none I know of like the verbosity of Java.
An ML or Haskell styled Javascript might fare better.
Here is my problem. Nothing is Google-able. Even basic things that I get caught up on the answer on IRC is usually "look up how to do it in JS, and then reform it to CS". Maybe I'm starting on the wrong stuff, but even though the syntax is wonderful, actually using libraries is a pain. I'm only on my 2nd day though, so maybe this is just the normal language growing pains.
Maybe that is your source of confusion.. when you write CS code, you can use any existing JS library. The syntax is just different for what you write.
Other than that I see a lot to like in CS though.
The only real problem is that debugging with CoffeeScript adds an extra layer of complexity. I know that this is more or less inevitable, but it is really the only major pain point that I encounter on a day-to-day basis.
* packaging, how do I import modules or packages? Do these even exist?
* debugging, how do I do this?
* unit testing?
I installed CoffeeScript via node, then npm (node package manager) and am using it via the command line.
Something like the ipython (http://ipython.scipy.org/moin/) shell along with pdb (http://muffinresearch.co.uk/archives/2008/04/27/python-debug...) would help immensely in my adoption of CoffeeScript.
In a perfect world the repl/debugger would be built into the webapp and open a websocket to another webapp so I could introspect/debug the page from another page while it was running (turtles all the way down). This is similar to the workflow for developing server side software (Jython, Python, Java).
* in firebug / web inspector
* qunit, jasmine etc
repl for node
### REPL ###
repl = require 'repl'
r = repl.start 'REPL> '
r.context.client = -> exec("open http://localhost:# {config.port}/") ; returnFor details about modules: http://nodejs.org/docs/v0.4.8/api/modules.html
Use the same site for the rest of the API too of course.
I like vows.js for unit testing: http://vowsjs.org/
In terms of complaints, I'd say the main one is a few things missing from the big page of documentation that's on coffeescript.org - #'s are comments, function calls with multiple arguments need to have the left paren start immediately after the function name, how to pass anonymous functions. Those cost me a few hours taken together starting out.
(I mostly work with Objective-C native apps and Ruby backends, so I'm not a JavaScript programmer--more like a user. A web view needs to frob the DOM or do some AJAX or something.)
A project came up where I needed to write the skeleton for a simple single-page web app component of a larger system. The window has a few panes which need to do AJAX, swap subviews in and out, and react to various inputs. Simple, but it has a few different view controllers and different kinds of data objects, so I decided to use this project to try CoffeeScript.
Comapared with JS, CS is much more concise and instantly readable. I think basically everybody agrees about that. It makes even Ruby feel a bit clunky with all the extra typing. ;-)
But surprisingly, there are no significant drawbacks. Debugging, the issue I had been wondering about, turned out to not actually be a problem at all. Two lines of CS code might be compiled to a sixteen lines of JS, but it's obvious what is going on, and debugging is effectively just as easy as ever.
So, two weeks in, I am reasonably sure that I will never write in raw JavaScript again. I just can't imagine why I would ever again type "function() {" three times to write one spec, or write my own for loop just to iterate a collection, or spend my time mentally filtering out all those braces and semicolons.
Granted, I am not mainly a JS coder, so my perspective is not the same as, say, a frontend dev to whom JS is second nature and 'the good parts' are deeply ingrained. My hunch is, though, that even if I was I would still switch.
The end result is the same, but the process of reading (and writing) the code is much nicer.
Guess which is more valuable :)
In practice, though, I frequently need/want to call a method as a callback. And inside that function, I might want to get something from whatever initiated the callback, and save it to the object I'm a method of. Ie, I want to access both forms of 'this'. So I still need to do the ;that = this' hack, ugly as it may be.
It would be super awesome if there was something that always referred to the topmost class object, and something else that always referred to the initiating object if one exists.
That said, I still like Coffeescript, was surprised to see how much Brenden Eich likes and supports the project at JSConf, and wouldn't be surprised if they addressed niggles like this in future.
AccountView.prototype.render = function() {
$(".account").click(function(e) {
// `this` is now the same as `e.currentTarget`
// But `e.target` is also useful.
// And you what you really want is for `this`
// to still point at the AccountView instance.
});
}; AccountView.prototype.render = function() {
$(".account").click( { that: this }, function(e) {
// 'that' now holds a reference to AccountView
});
};
If you don't want to use (or you are using an older version of jquery without the eventData) you could use a closure: $(".account").click( (function(that) {
return function(e) {
// 'that' now holds a reference to AccountView
})(this);
});You realize you're replying to the author of CoffeeScript?
Yes.
> and isn't a jQuery callback?
No :^). And I wish JQuery ran the callback with a parameter too, so I could access 'this' to refer to the class and use the argument to refer to the object I'm going to run the callback on.
You're totally right that would be neater. Alas Coffeescript is a lot newer than JQuery, so despite technical neatness (or lack thereof in JQuery), Coffeescript has to work with JQuery to grow in popularity.
PS. Thanks for making Coffeescript. It's got me excited about JS again and I absolutely love it.
class Widget
render: ->
$(".widget-title").click (e) =>
# `this` is still the Widget instance.
# `e.currentTarget` is the DOM element.click() works because the callback is given parameter:
.click( handler(eventObject) )
Cool. You access @ for the class, and eventObject for the thing you clicked.But I wasn't using click(), I was using load(), which has a different syntax:
.load( url, [data,] [complete(responseText, textStatus, XMLHttpRequest)] )
I may be missing something - I only started doing JS seriously last year - but 'complete' doesn't seem to be provided with any parameters, like the element I just loaded. So my only choice, AFAICT, is to use 'this' to access that element. I'd be delighted if that was wrong though. :^)Background: I was trying to get the width of an image file that wasn't in the document, so I could use it to size another image (which happened to use the first image as a webkit mask). Great fun.
I have Vim all set up to auto-complete it, to syntax highlight, and to auto-compile whenever I save. The bad news is: No Eclipse plugins, no notepad++ plugins. etc. So the only other devs who can work on it are on Mac and Linux (which to be fair, half of my company are on Ubuntu, but there's that 1/3 of the company on Windows that just can't practically work on coffeescript code).
I'm using the former. It's usable, but lacks somethings like fixing indentation errors automatically, and auto-completion. Also the default colors under twilight theme are unreadable, so you have to modify those yourself.
I wan't to be able to debug the code I'm writing in the code I'm writing. The extra layer of sugar seems sickly sweet, nice for a taste but overpowering in bulk.
I think I'm prone to wanting to go lower and seeing how things work in the layer beneath. I'm fascinated by C and assembly languages and how my JS ultimately sits on top of those. I think if CS was interpreted at the same level as JS I'd be more interested.
I guess it really depends on how much you use JS and whether CS makes your work easier. I'm always looking at what complexity I can throw away, I think CS may be just that.
For example, in my app (http://iphone.albumpl.us) I had to write a couple of small custom objective-c modules to get some camera/image stuff to have sufficient performance. But overall being able to write most of it in CoffeeScript, is so much better (enjoyment-wise and speed-wise) than having to write everything in objective-c.
A trivial example (ignore style), project euler problem 1:
(x for x in [0..999] when x % 3 is 0 or x % 5 is 0).reduce (xs, x) -> xs + xCoffeescript curates the good parts of javascript for you and adds the syntactic sugar that cleans up the gnarliness of javascript.
The other day I found the code to a shoot-em-up I wrote in 2002 and it ran in Chrome with no changes required! Sure, the code was very "DHTML"-y, but that's pretty cool!
To those more experienced: at some point does thinking in pure coffeescript take over, and the JavaScript transforms disappear?
It is worth noting, my final coffeescript code is a thing of beauty!
However, if someone told me that Coffeescript was going to vanish forever from tomorrow on, I don't think I would be heartbroken.
Positive about it, though. I'll be using it in the future but not quite the 'next opportunity'.
Also, I never understood why some people advocate learning C++ before C. But that's a different debate...
It's amazing what a more concise and logical syntax can do. While I think the language isn't perfect, it does just enough clean up on Javascript to make a huge difference.
Being a Ruby shop, CoffeeScript (CS) has been a choice for us. We simply find it is a good fit for our minds and how we like to write code, makes it that much easier to structure and organize code nicely, and is more pleasant to look at day in and day out.
Anyway, CS would be my second choice but that’s just because I work in .NET environment.
As far as I know CoffeScript requires node.js, npm and cygwin. Am I wrong?
https://github.com/alisey/CoffeeScript-Compiler-for-Windows
And it doesn't require cygwin. I haven't tried it myself but it's the route I would go.
Cygwin is the current way of "Node on Windows" but there will be much better / "more native" Node support for Windows coming in the next 4-20 months ;)) anyway, you don't need Node for Coffee. It only provides the Node integration pieces because the developer(s) do a lot of Node work themselves and it's a great way to write server-side code for Node for people coming from Python/Ruby etc.
If you're using CoffeeScript without Node, you're missing out. Fortunately, Cygwin-free Windows support is on the roadmap for Node 0.6.
I still don't see the bloody point.
JS is alright, dammit. You don't need CS, you need to get your shit done.
Is it only me who likes JS better than CS? :( It's stylish.
It's all about power, flexibility, succintness and readability, all things that make programming more enjoyable and fun.