

Defer: Taming asynchronous javascript with coffeescript - gfxmonk
http://gfxmonk.net/2010/07/04/defer-taming-asynchronous-javascript-with-coffeescript.html

======
pc
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.

This is what frameworks like Seaside do.

~~~
gfxmonk
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.

------
jashkenas
For extra reading material for the curious, the history of the proposed
implementation of "defer" in CoffeeScript:

Part I: <http://github.com/jashkenas/coffee-script/issues/issue/241>

Part II: <http://github.com/jashkenas/coffee-script/issues/issue/287>

Part III: <http://github.com/jashkenas/coffee-script/issues/issue/350>

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.

------
axod
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).

~~~
ekidd
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?

async function (x) { return x; } =>

function (x, callback) { callback(x); }

~~~
gfxmonk
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 :)

------
_delirium
Apart from being a cool bit of tech, this is a really good writeup.

------
cageface
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.

~~~
jashkenas
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:

[http://ejohn.org/blog/javascript-language-
abstractions/#comm...](http://ejohn.org/blog/javascript-language-
abstractions/#comment-323770)

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):

[http://jashkenas.s3.amazonaws.com/misc/buddhabrot/buddhabrot...](http://jashkenas.s3.amazonaws.com/misc/buddhabrot/buddhabrot.html)

Here's the CoffeeScript that runs it:

<http://gist.github.com/463880>

And here's the compiled JS (not too different):

<http://gist.github.com/463881>

~~~
cageface
Thanks for the explanation. It's definitely a cool hack. Looks like a fun
project.

------
Mathnerd314
Why not call it callCC instead of defer? Aside: great intro to continuations,
I now understand them!

~~~
fserb
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.

