The problem is simply that those languages are not Lisp. Once good patterns of use of GOTO were found, it was natural to critisize random uses, and to wrap good uses in a lisp macro. Or in a new while or for "instruction". But then the next construct is discovered, and its bad uses considered harmful, and its good uses need to be wrapped. In lisp, mere programmers will just write the next macro to abstract away this…
Callbacks as our Generation's Goto Statement
121–130 of 287 posts
Re: Callbacks as our Generation's Goto Statement
#122I 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 d…
How do you do this with callbacks? foreach (var player in players) { while (true) { var name = await Ask("What's your name"); if (IsValidName(name)) { player.name = name; break; } } } Assuming `Ask` is an asynchronous operation and must not block the UI thread. Note that second player is only asked after the first player has given a valid name. (And the code structure reflects that :-) My point is of course it's doab…
Re: Callbacks as our Generation's Goto Statement
#123Earlier 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.
Re: Callbacks as our Generation's Goto Statement
#124Yes I know a lot of standard libraries have calls that are async and you may not really need for them to be async but I don't think that this is the case often enough that we should abandon callbacks and the like and go back to an age where all code must be synchronous. I know the author isn't saying it to that extreme necessarily, but his comparing callbacks to gotos is extreme as well.
Re: Callbacks as our Generation's Goto Statement
#125The problem is simply that those languages are not Lisp. Once good patterns of use of GOTO were found, it was natural to critisize random uses, and to wrap good uses in a lisp macro. Or in a new while or for "instruction". But then the next construct is discovered, and its bad uses considered harmful, and its good uses need to be wrapped. In lisp, mere programmers will just write the next macro to abstract away this…
Ah, but the real problem is not that these languages aren't Lisp, but that they aren't Scheme. People are being forced to write continuation-passing-style code by hand, which anyone would agree is painful. To allow user-level code to abstract away the need to write CPS, you need call/cc (or something like it).
Re: Callbacks as our Generation's Goto Statement
#126The key I've discovered to nicely organizing callbacks is to avoid anonymous callback functions unless absolutely necessary for a particular scope, or unless the function is going to be so trivial and short that it can be read in a single glance. By passing all longer, non trivial callback functions in by name you can break a task up into clear functional components, and then have all the asynchronous flow magic happen in one concise place where it is easy to determine the flow by looking at the async structure and the function names for each callback function.
Another major advantage to a code organization like this is that once you have your code such that each step has it's own discrete function instead of being some inception style anonymous function tucked away inside another function inside another callback it allows you to properly unit test individual functional steps to ensure that not only is your code working and bug free at the top level functions, but also that each of the individual asynchronous steps that may make up some of your more complicated logic are working properly.
Most of the bad examples of callback hell that I see have anonymous callback functions inside anonymous callback functions, often many levels deep. Of course that is going to be a nightmare to maintain and debug. Callbacks are not the problem though. Badly organized and written code is the problem. Callbacks allow you to write nightmarish code, but they also allow you to write some really beautiful and maintainable code if you use them properly.
Re: Callbacks as our Generation's Goto Statement
#127Evan Czaplicki (author of Elm lang) made the identical argument (sometime?/years ago), with the same reference to Dijkstra's quote, but with another suggested solution, Functional Reactive Programming, on which his language is oriented: http://elm-lang.org/learn/Escape-from-Callback-Hell.elm
HN discussion of that article: https://news.ycombinator.com/item?id=4732924 FRP is an interesting topic (I thought so anyway, I wrote a paper on it for my MS). It doesn't seem to have caught on widely as a paradigm, with a few exceptions I'm aware of (Elm, Meteor).
Re: Callbacks as our Generation's Goto Statement
#128"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 c…
Re: Callbacks as our Generation's Goto Statement
#129Can someone explain to me the difference between this and futures (specifically, futures in c++11)?
Re: Callbacks as our Generation's Goto Statement
#130I 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 d…
How do you do this with callbacks? foreach (var player in players) { while (true) { var name = await Ask("What's your name"); if (IsValidName(name)) { player.name = name; break; } } } Assuming `Ask` is an asynchronous operation and must not block the UI thread. Note that second player is only asked after the first player has given a valid name. (And the code structure reflects that :-) My point is of course it's doab…
function makeAskPlayer(i) {
return function askPlayerHisName() {
console.log("askPlayerHisName: " + i);
Ask("What's your name?", function(name) {
if (isValidName(name)) { players[i].name = name; }
else { return (makeAskPlayer(i))(); }
// name was valid, get next one
if (i
Here's a simple test case showing it works: http://jsbin.com/ojakuy/2/edit. You need to open the console to see the output.