Nitpick: the beautiful thing about Smalltalk's continuation support is that it's not provided by the compiler. (As far as I know, Squeak still doesn't ship with continuation support built-in.)
Despite this, because stack frames are first class objects in Smalltalk, it's very easy for the user to implement continuations. You just traverse the stack to capture the continuation, and switch stack frames with the continuation's in order to invoke it. The resulting Continuation class is almost improbably literal in its implementation.
Thanks, good point. I actually meant to reference scheme, not smalltalk - as I believe that's where continuations were first done. I believe it is provided by the runtime in scheme (but still, not the compiler). I've corrected the post now.
If you have a suggestion for how to handle the bits of "defer" that are still undecided, such as how to handle the "return" statement, and enforce a callback parameter, please feel free to add it to the third ticket.
Good intro to continuations, but just reinforces the reasons I dislike them and wouldn't use them.
Also disagree about "What is asynchronous programming, and why is it so damn awkward?"
It's not awkward in the least. Either you write your code to remember the things you need to remember, or you use something like continuations which will be pretty inefficient and ugly (IMHO).
Continuations can certainly be ugly (under some circumstances), and difficult, too. But there's no reason why this particular implementation of continuations needs to be inefficient—it has a one-to-one mapping with ordinary asynchronous JavaScript, and it generates exactly the code you'd otherwise write by hand.
Overall, I think this is a win for clarity. But I think the author should also transform functions that take a callback argument, and implicitly convert them to continuation style. Perhaps this could by adding the callback parameter automatically and transforming 'return' into a callback invocation?
Regarding transformations of returns, the initial implementation added an anonymous callback argument and converted returns into using it. But that takes the option of using the callback out of the programmer's hands, and is entirely non-obvious for someone calling the function (the number of parameters required is one more than those listed in the function definition)
I plan to write a follow-up shortly that discusses possible approaches of doing this sort of thing, and your suggestion is one of the ideas I'm going to explore. Thanks for reading & commenting :)
I'd like to see an example of nontrivial asynchronous code that isn't at least a little awkward.
continuations may well be inefficient, it depends on the runtime. `defer` does not implement real continuations, so that's largely irrelevant - there is no runtime overhead that you don't already have by writing your own callback functions.
As for ugly, do you refer to the compiled output, or the source code? gcc outputs some pretty ugly assembly code; does it matter?
Things like Coffeescript and Objective-J make me nervous. Javascript is flawed certainly but building a completely new language on top of it feels too radical. An abstraction like that seems bound to be leaky and it doesn't seem like you'll ever completely escape working with other native JS pieces so why not stick to a single, common syntax with good tool support, tutorials, docs, libraries etc? Javascript's not that bad a language once you establish some conventions.
CoffeeScript is just for fun -- it's a thought experiment that tries to see how far we can run with JavaScript semantics towards a more usable language.
Apart from the fact that both compile to JavaScript, CoffeeScript and Objective-J don't really sit together in the same boat. Objective-J is an actual runtime and interpreter: every single method you call is intercepted and handled by "objj_msgSend", so that things like method_missing are possible. See:
CoffeeScript limits itself to current common patterns of JavaScript in practice, and (in a perfect world) would compile 1-to-1 into the JavaScript you would have written. Unlike an implementation of Ruby or Python in JavaScript, where even simple things like numbers work quite differently, the semantics of CoffeeScript are just JavaScript semantics -- so there shouldn't be anywhere for the abstraction to leak.
As to sticking to a single common syntax -- that's a very good argument, and I'd have hesitations introducing CoffeeScript into a team project. But if you just want to play around with a fun way to write JS. I encourage you to give it a spin. For an example, take a peek at this implementation of the Buddhabrot fractal (the render will peg your CPU, so use Chrome):
I don't know where to draw the line exactly, but I wouldn't call them completely new languages. Coffeescript is basically another syntax for JavaScript and Objective-J adds a few bits of syntactic sugar. The latter, of course, is pretty equivalent to what Objective-C does to C, Coffeescript reminds me a bit of Ratfor.
Considering the unstructured default nature of JavaScript and its flexibility, I would say that you can get much farther of the trodden path by just using certain libraries. Adapting to a different syntax that just expresses things slightly different/shorter than you'd usually do things isn't as hard as actually doing things a different way. Straightforward jquery written in Coffeescript should be easier to understand than code that heavily uses wu.js, underscore and/or js.class.
Of course, Objective-J has both syntactic additions and a huge Library tacked on. It's more meant to people who already work with Cocoa, so that their adjustments have to be minimal than for people coming from JavaScript.
Coffeescript doesn't really compare to that. It's actually pretty minimal, and you shouldn't have trouble using it with JavaScript libraries, unless they depend too much on certain syntactic stylings (I bet fab.js won't play nice).
Considering the unstructured default nature of JavaScript and its flexibility, I would say that you can get much farther of the trodden path by just using certain libraries.
Wu.js (thanks for the link) still looks like Javascript to me and won't cause any problems with Firebug or Emacs. Coffeescript and Objective-J have a completely different syntax. I can believe that Coffeescript is easier to read but it doesn't seem like enough of a win to break tool support and to work in two completely different syntaxes (inevitably there will still be plain js to deal with in most projects).
Objective-J seems even riskier. I can see the appeal for Cocoa people but you're really going all-in with that kind of framework.
Yes, Cappuccino is an all or nothing framework, it's not meant for interoperability with other JavaScript libraries. You'd have to like the whole deal.
I don't have a big problem with switching between CoffeeScript and regular JavaScript, though. I'd regard it as some kind of shorthand for writing code, similar to what more elaborate template languages (haml etc.) do to HTML. It doesn't do weird transformations (last time I looked at it), so you should be able to debug the produced code.
Right now, I'm not using it in any production code, as for simple client-side programming with JQuery, it's not a big win. I'm seriously considering it for a future node.js project, though. I found myself using too many snippets when writing JavaScript code, which reminds me to much about my last Java projects…
I think you almost answered your own question. callcc makes people have to understand continuations and is confusing, while "defer" fits better with the control flow that most people have in mind already.
Despite this, because stack frames are first class objects in Smalltalk, it's very easy for the user to implement continuations. You just traverse the stack to capture the continuation, and switch stack frames with the continuation's in order to invoke it. The resulting Continuation class is almost improbably literal in its implementation.
This is what frameworks like Seaside do.