Live data from Hacker News

Callbacks as our Generation's Goto Statement

tirania.org

131–140 of 287 posts

Re: Callbacks as our Generation's Goto Statement

#131

Earlier quoted context omitted.

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…

I'd do that with the aforementioned `async` library, specifically `async.eachSeries`: async.eachSeries players, ask, -> # Well that was easy enough... printRoster(players)

Where is the part that checks if the name was invalid and then asks again?

Re: Callbacks as our Generation's Goto Statement

#132
I was expecting to read something about FRP or other naturally reactive programming models that dealt with the semantic complexity of callbacks, not just their syntactic complexity. I don't think async constructs and others that depend on CPS techniques are really going to save us from complex programs that we barely understand.

Re: Callbacks as our Generation's Goto Statement

#133
I have a basic technical question. I work in C for embedded systems, so I'm a bit "behind the times."

How is "await" any different from a regular blocking system call? A regular system call does exactly what is being described: The system call happens, and then when it is finished, execution resumes where it left off.

(Yes, this makes the thread block... which is why you have multiple threads. I think the answer will have something to do with this, though...)

Re: Callbacks as our Generation's Goto Statement

#134

As someone who only recently switched to Node.js from PHP I personally haven't had any difficulty switching over to the callback frame of mind, and I haven't experienced the "callback hell" so many people complain about. At first I was hesitant to start with Node because I saw blog posts by people bemoaning the spaghetti callback code that they ended up with. But I haven't experienced any of that, although I am a rel…

I often write synchronous methods that include control flow that nests three deep (say try/finally, if/then/else, and a for loop). Often it's easier to read this code than it would be if everything were split out into separate named methods.

Why would the same not be true of asynchronous methods, assuming that the technology was there to enable it (as it is in C#)?

Re: Callbacks as our Generation's Goto Statement

#135

I think this article misses a main point and that's the fact that all await does it take a function that used to be asynchronous and makes it synchronous. While yes, there are definitely use cases where that is nice, in general I think that if you want to use an await command, why are you making a call that was meant to be async? You are defeating the whole point of async calls. Yes I know a lot of standard libraries…

That's not how async/await work at all. They let you write the code as if it were synchronous, but it's still asynchronous, which is the whole point.

Re: Callbacks as our Generation's Goto Statement

#136

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 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…

Here is an example where callbacks are even less intuitive:

  if not song.artist
    @getArtist song.id, (err, artist) =>
      song.artist = artist
      @save song
      @addToCatalog song
      #...
  else
    @save song
    @addToCatalog song
    #...
Callbacks will force you to move @save, @addCatalog, ... into a separate function. Completely messing up the logical sequence of operations.

Re: Callbacks as our Generation's Goto Statement

#137
post #3

Holy Baader-Meinhof, just today, in frustration, I wrote something like Haskell's sequence_ for ContT, in Javascript: https://gist.github.com/cscheid/6241817

Why do you as an American feel the need to invoke some dead german left-wing militants in a pseudo-religious phrase that's meaningless except maybe for shock value? This seems highly inapproriate for any website and even more so on HN.

(for whatever's worth, I'm Brazilian)

Re: Callbacks as our Generation's Goto Statement

#138

Why do people insist on analysing things using analogies? Analogies are useful for explaining a concept that might not be obvious. Saying callbacks are like gotos, gotos are bad, therefore callbacks are bad is ridiculous. And he gives some sample code where the 'problem' is nothing to do with callbacks, its just nested lambdas. In fact I find that code quite easy to read, and would be very interested in seeing the sa…

I'm confused as to why you think the code presented in the blog post isn't an example of 'the same functionality implemented some other way'. The await code is almost undeniably more straightforward and the exceptional cases more obvious to handle.

He also doesn't seem to be making a weird logical leap the way you claim he is. He's not really using an analogy. He's saying callbacks are bad the same way goto is bad, in that they make the logical structure of a program's execution non-obvious, particularly over time and when being modified.

Re: Callbacks as our Generation's Goto Statement

#139
post #133

I have a basic technical question. I work in C for embedded systems, so I'm a bit "behind the times." How is "await" any different from a regular blocking system call? A regular system call does exactly what is being described: The system call happens, and then when it is finished, execution resumes where it left off. (Yes, this makes the thread block... which is why you have multiple threads. I think the answer will…

The idea is that while you're waiting on some kind of I/O or other asynchronous activity to complete, the thread you're on can do some other work. Threads are relatively heavyweight compared to the sort of cooperative multitasking that can be done through await or callbacks.

Re: Callbacks as our Generation's Goto Statement

#140
post #134

As someone who only recently switched to Node.js from PHP I personally haven't had any difficulty switching over to the callback frame of mind, and I haven't experienced the "callback hell" so many people complain about. At first I was hesitant to start with Node because I saw blog posts by people bemoaning the spaghetti callback code that they ended up with. But I haven't experienced any of that, although I am a rel…

I often write synchronous methods that include control flow that nests three deep (say try/finally, if/then/else, and a for loop). Often it's easier to read this code than it would be if everything were split out into separate named methods. Why would the same not be true of asynchronous methods, assuming that the technology was there to enable it (as it is in C#)?

I agree. Sometimes inline asynchronous callbacks work, just like inline code blocks for if statements or for loops. You just need to train your eye to read them as if they were inline code blocks for an if/then/else block or a for loop.

But sometimes when you get many levels deep in if statements or if a synchronous function starts to reach the hundreds of lines it makes sense to break it up into multiple functions that each have a sensible semantic meaning and which fit on a screen or so. This makes the synchronous code easier to read.

The same goes for asynchronous callback functions. The callback hell that I see most often happens when people have hundreds of lines of inception style anonymous callback functions inside of anonymous callback functions. In this case, just as with the synchronous function that got excessively heavy it makes sense to break things up into multiple functions.

It's all about finding the right balance, and when you do the results are very readable and easy to understand whether you are writing synchronous or asynchronous code.

Post reply on HN