ToffeeScript – CoffeeScript with async syntax and some additional features(github.com)
github.com
ToffeeScript – CoffeeScript with async syntax and some additional features
https://github.com/jiangmiao/toffee-script
25 comments
I've never really understood the problem with "callback hell" that people talk about. The biggest annoyance I've seen from it is that indentation can get a little out of hand, but the examples I've seen could be fixed with smarter coding rather than new language features.
I love asynchronous programming and prefer callbacks over other forms of asynchronous flow control... but callback hell is a real problem. It's easy to lose track of the logic flow and hard to coordinate several parallel callbacks without external libraries such as node-async.
Smarter coding does not fix the callback pyramid either, because then your callback logic is spread through the source and not where it belongs, making things even worse!
And when your callbacks depend on each other it's REAL HELL, because it's easy to create a tangle of mutable closed variables far from the real logic which IMHO is not a very good pattern. I tend to prefer functional programming with pure functions, but callback-hell-code can quickly resemble the worst parts of OOP if you're not careful (without the good parts such as encapsulation).
I love Node.js, it's my platform of choice, but big projects can quickly get out of control. I'm really looking forward to generators to fix the issue.
I couldn't understand callback hell either, until I really got into Node.js programming for big projects.
Smarter coding does not fix the callback pyramid either, because then your callback logic is spread through the source and not where it belongs, making things even worse!
And when your callbacks depend on each other it's REAL HELL, because it's easy to create a tangle of mutable closed variables far from the real logic which IMHO is not a very good pattern. I tend to prefer functional programming with pure functions, but callback-hell-code can quickly resemble the worst parts of OOP if you're not careful (without the good parts such as encapsulation).
I love Node.js, it's my platform of choice, but big projects can quickly get out of control. I'm really looking forward to generators to fix the issue.
I couldn't understand callback hell either, until I really got into Node.js programming for big projects.
well, imagine you have 4/5 sequential db calls, and for each async call need to write a success callback and a failure callback ...
async lib helps though defer/await programming style would be a better option.
[deleted]
It looks like a CPS transform, which can be very useful; but I think it's something you'd rather opt in to rather than apply everywhere.
Is there something similar (i.e. syntactic sugar/macros for defining callbacks that provide similar functionality) for "plain" javascript as base language?
StratfiedJS (http://onilabs.com/stratifiedjs) does this and more[0]. It's more heavyweight than a set of macros, but we believe the features warrant that.
[0] including a module system, fork-join parallelism, try/catch and stacktrace support even for async code.
(disclaimer: I joined Oni Labs to work on SJS, after struggling with my own coffeescript fork for 6 months)
[0] including a module system, fork-join parallelism, try/catch and stacktrace support even for async code.
(disclaimer: I joined Oni Labs to work on SJS, after struggling with my own coffeescript fork for 6 months)
There's tamejs (https://github.com/maxtaco/tamejs)
Could someone please explain what's Callback hell and why Toffee-script is doing to resolve it? The compiled JS code looks harder to read than using callbacks to me.
“Callback hell” is when you need to do many asynchronous actions / call several asynchronous APIs with inputs to each call depending on the delayed results of some other call(s), and you are using callbacks to organize your control flow. Often you end up with either a large set of named functions being passed around as callbacks, or a deeply nested hierarchy of anonymous callbacks. Either way, control flow can be difficult to follow or reason about, both when reading the code and when debugging. Even simple tasks take large amounts of boilerplate code.
The generated code is using callbacks. The point is that instead of writing something like (a cleaner, but still ugly, version of) the generated code on the right, you’d instead write the (quite easy to read) toffeescript code on the left.
That said, I think coffeescript’s “it’s just javascript” slogan (and goal of generating readable code) is one of its most important features. It has to be quite a bit harder to debug than the coffeescript version, since the generated code has control flow that’s so different looking from the input.
The generated code is using callbacks. The point is that instead of writing something like (a cleaner, but still ugly, version of) the generated code on the right, you’d instead write the (quite easy to read) toffeescript code on the left.
That said, I think coffeescript’s “it’s just javascript” slogan (and goal of generating readable code) is one of its most important features. It has to be quite a bit harder to debug than the coffeescript version, since the generated code has control flow that’s so different looking from the input.
What did you use to create the generated JavaScript? I'm still new to this and trying to figure out out.
toffeescript is a language which has a compiler that generates Javascript.
Callback hell is what you get when you take a language designed for doing at most client-side input validation, and try to write serious applications in it.
As an analogy, consider what would happen if Outlook was written in VBA and you opened OUTLOOK.DOC in Word to read your email. Well that's GMail.
As an analogy, consider what would happen if Outlook was written in VBA and you opened OUTLOOK.DOC in Word to read your email. Well that's GMail.
http://callbackhell.com/
That explains the many ways to structure your async code in pure JavaScript (no helper libraries or transpilers) so you don't create callback hell code.
That explains the many ways to structure your async code in pure JavaScript (no helper libraries or transpilers) so you don't create callback hell code.
> The compiled JS code looks harder to read than using callbacks to me
With good tools and a sufficiently correct compiler, that should be as irrelevant as worrying that compiled x86 assembly is harder to read than the C source.
With good tools and a sufficiently correct compiler, that should be as irrelevant as worrying that compiled x86 assembly is harder to read than the C source.
http://opalang.org/ has something like that. I do find it a lot easier than all other proposed solutions so far. Wish a language like Clojure(script) would have something like this for general use with async processes/callbacks (in Java/.NET running threads, in JS this).
Is this just like C#'s async, F#'s mon^H^H^H workflows aka computation expressions, Haskell's do notation?
Not at all in the case of Haskell whose IO is automatically async. You write IO in a normal blocking style and your current thread will automatically be suspended and resumed.
You are just required to do it in the IO monad since the language is pure.
While it may be slick, it does violence to the call stack which will grow tremendously with the size of your functions. Plus, it's very hard to optimize any of the generated code since it contains so many jumps and context switches.
I'm actually more excited about the Ruby-style pattern matching. The last time I had to do that in Coffee I was wishing for that syntax.
I'll need to see more real world examples to decide if Toffee's async syntax is better than Iced.
I'll need to see more real world examples to decide if Toffee's async syntax is better than Iced.
I don't understand what the Basic example is supposed to do:
var x, y, _this = this;
a(b, function() { x = arguments[0], y = arguments[1]; return console.log(x, y); }); ReferenceError: a is not defined
var x, y, _this = this;
a(b, function() { x = arguments[0], y = arguments[1]; return console.log(x, y); }); ReferenceError: a is not defined
a is a function which would already be defined at this point. Anything after the exclamation point is arguments to the callback function. Any following code is wrapped in an anonymous function passed as the final argument to the function a.
Anything on the left-hand side of the assignment (in this case, x and y) are arguments passed to this anonymous function. A concrete example of why you would do this would probably be useful.
Anything on the left-hand side of the assignment (in this case, x and y) are arguments passed to this anonymous function. A concrete example of why you would do this would probably be useful.
Here's a somewhat contrived example which I haven't tested, but I think illustrates the point although this particular case is probably better handled by other syntax presented later in the README.
err, data = fs.readFile! path
{
err, data = fs.readFile! path
{
if (err) throw err;
console.log data
}