Live data from Hacker News

Callbacks as our Generation's Goto Statement

tirania.org

31–40 of 287 posts

Re: Callbacks as our Generation's Goto Statement

#31
"Await" is fantastic, and having using it for JavaScript (via TameJS and then IcedCoffeeScript), it makes things a lot easier and clearer.

That being said, I don't think the comparison between callbacks and goto is valid.

"Goto" allows you to create horrible spaghetti-code programs, and getting rid of it forces you to structure your programs better.

"Await", fundamentally, isn't really anything more than syntactic sugar (except for exception handling, which is a good thing). "Await" doesn't change how your program is structured at all, it just changes the visual representation of your code -- from indentations in a non-linear order, to vertical and linear order. It's definitely a nice improvement, and makes code easier to understand (and allows for better exception handling), but it's not actually changing the way your program is fundamentally structured.

And finally, "await" is only applicable when a single callback gets called once at the end. If you're passing a callback that gets used repeatedly (a sorting function, for example), then normal-style callbacks are still necessary, and not harmful at all. Sometimes they can be short lambdas, sometimes they're necessarily much larger.

In sum: "await" is great, but there's nothing inherently harmful about callbacks, the way "goto" is. To the contrary -- callbacks are amazingly useful, and amazingly powerful in languages like JavaScript. "Await" just makes them nicer.

Re: Callbacks as our Generation's Goto Statement

#33
post #6

This is what continuations are for.

Continuations don't help with the problem that the visual structure of callback-oriented programs doesn't reflect the order of execution. As a heavy JS programmer, that's the most compelling point for me in this post.

Actually, they do. C#'s await (and any similar scheme based on ES6 generators) is a feature that can be built using continuations.

Re: Callbacks as our Generation's Goto Statement

#35
In the right places and for the right reasons they are fine. A lot of code today devolves into what I've come to call "callback spaghetti" and, well, good luck. The toughest thing sometimes is getting your mind around what is supposed to happen and, more importantly, what is not.

I found that sometimes it helps to build a state machine to effectively run the show and try to limit callbacks to setting flags and/or navigating the state tree. State machines make following code functionality a breeze, even when dealing with really complex logic.

Re: Callbacks as our Generation's Goto Statement

#36
post #30

Earlier quoted context omitted.

This sounds sweet. In my book, C# designers have a history of striking a good balance between simplicity and flexibility. This however always leaves me eager to look at Haskell/ClojureScript/other languages where concepts that C# borrowed and simplified are taken to the full (such as monads, iterators, CSP, etc).

The C# designers outdid themselves this time. I'm surprised they managed to made this feature so simple and succinct, especially for an "enterprise" language. Those two little words (async/await) seem like something I would expect from a language like Python or Ruby. Had it been Java, it would be called AsynchronousBureaucraticProccessDispatcherFactoryFactoryFactory.

F# implemented this many years before (6 years ago), and as a library, just by providing the proper language feature, workflows, and a default async implementation.

In comparison, C# adds special compiler keywords for one specific example, just like they did with LINQ. That seems rather ugly IMO. Providing building blocks and letting libraries fill things in is a lot nicer.

This is more of a "C#'s finally catching up with basic features".

Re: Callbacks as our Generation's Goto Statement

#37
I don't understand what the big deal is. Callbacks are OK. They're less cumbersome if the language you're using has smaller function definitions.

Callbacks 'get crazy' when you've got more than one I think, and thankfully someone smart has made a library you can use to manage them!

https://github.com/caolan/async

Saying that, I don't mind the way things look with the whole await/async stuff in C# and etc. However I don't think we should be waving our arms around saying callbacks are like goto, they so completely are not! I have written heaps of stuff with callbacks and it's _not that confusing or unmaintainable_. It's just different.

Re: Callbacks as our Generation's Goto Statement

#38
post #6

Earlier quoted context omitted.

Continuations don't help with the problem that the visual structure of callback-oriented programs doesn't reflect the order of execution. As a heavy JS programmer, that's the most compelling point for me in this post.

Actually, they do. C#'s await (and any similar scheme based on ES6 generators) is a feature that can be built using continuations.

So are Java/C#/everything-else exceptions. And, for that matter, pretty much every control flow construct imaginable.

OTOH, I think that the big problem with continuations is that it gets very difficult to build efficient implementations of them (and this tends to impact not just efficiency of code that uses continuation, but usually efficiency of any code in a language which supports them), and it is much more efficient to implement specialized weaker (but good enough for most key use cases) forms of the most important applications of continuations.

Re: Callbacks as our Generation's Goto Statement

#39

"Await" is fantastic, and having using it for JavaScript (via TameJS and then IcedCoffeeScript), it makes things a lot easier and clearer. That being said, I don't think the comparison between callbacks and goto is valid. "Goto" allows you to create horrible spaghetti-code programs, and getting rid of it forces you to structure your programs better. "Await", fundamentally, isn't really anything more than syntactic su…

You're missing the point of `await`.

Await does change how your program is structured, unless we're talking about most trivial cases.

You can use `await` inside a `for` loop—can you do the same with callbacks without significantly re-structuring your code?

What is the “callback analog” of placing something in a `finally` block that executes no matter which callback in a nested chain fails? You'd have to repeat that code.

Await has a potential of simplifying the structure a lot, because it befriends asynchronous operations with control flow.

>And finally, "await" is only applicable when a single callback gets called once at the end. If you're passing a callback that gets used repeatedly (a sorting function, for example), then normal-style callbacks are still necessary, and not harmful at all.

Indeed, await is only for the cases when we abuse functions (because we don't know what we'll call, and we have to bend our minds). Passing the sorting comparator is the primary use of first-class functions.

Re: Callbacks as our Generation's Goto Statement

#40
lthread is a coroutine library that allows you to make blocking calls inside coroutines by surrounding the blocking code with lthread_compute_begin() and lthread_compute_end(). This is equivalent to async calls but without the need to capture variables.

http://github.com/halayli/lthread/

Disclaimer: lthread author

Post reply on HN