Since CoffeeScript is a new language that can evolve quickly, and since one of its main use cases is Node, and since Node relies heavily on callbacks... why not add some sugar to make callbacks a bit nicer? I propose a way to bind callback arguments to left-hand variables. This is actually pretty similar to what Haskell does with its do notation, and for pretty similar reasons.
Let's take a simple, imperative-with-exceptions snippet of code:
try res1 = func1 arg1 [res2a, res2b] = func2 res1 if res2a is "foo" doFoo() else res3 = func3 res2b doBar res3 catch err handle err
That's pretty simple. Watch how gross it turns when we use callbacks instead of just returning back the results:
func1 arg1, (err, res1) -> if err? handle err else func2 res1, (err, res2a, res2b) -> if err? handle err else if res2a is "foo" doFoo() else func3 res2b (err, res3) -> if err? handle err else doBar res3
My suggestion is to create some sugar for that. It would look something like this:
do and throw err... (err, res1) <- func1 arg1 (err, res2a, res2b) <- func2 res1 if res2a is "foo" doFoo() else do... (err, res3) <- func3 res2b doBar res3 catch err handle errNotice how similar this is to the original, easy-to-read, imperative style. The general idea is simple: the new
do...syntax introduces a block of code in which callback variables can be bound on the left-hand side. Every time that happens, it starts a new callback nested in the previous one. If you provide the
and throw varnamesyntax, then it treats left-hand bound variables of this name as errors, and if one ends up being non-null, its callback will run the code in the
catchblock and nothing else.
I won't pretend this is a small bit of sugar; it probably has some interesting edge cases, and the concept might be a bit weird to grok for someone who's new to it. But it's an elegant solution to a real problem that's pretty significant for a major part of CoffeeScript's target audience.