3 ms·
The article complains that async/await 'infects' all the code that touches it and forces the callers to use async/await too. But isn't the same true with go ch
by delegate 2y ago
The article complains that async/await 'infects' all the code that touches it and forces the callers to use async/await too.
But isn't the same true with go channels ? If you want to asynchronously interact with a channel (that is, without blocking the main thread), you have to do it in a go block and the caller has to do the same and so on ?
Promises behave similarly - must wrap your code in promises all the way.
These constructs are alternatives to the good old callbacks, which force you to write your code inside callbacks, thus 'infecting' everything and leading to callback hell.
This 'cascade infection' effect is due to the inherent nature of things happening asynchronously, which contradicts the synchronous program flow inside a thread, so when the async event terminates, the program has to jump to a handler in order to process the results.
In the end it's a matter of taste imo..
- fer 2y agoIt's the same for many things. Java throws, const-correctness in C++, etc, etc. As some other comment said, it's like the Haskell IO monad and that's OK, because it lets you isolate and be aware of the implications of that code.
- instig007 2y agoHaskell has <$> and the infrastructure of HKTs to stop this infectious propagation of IO, other languages do not, and their async/await colors do not isolate side-effectful actions from the rest pure parts of your codebase. https://hackage.haskell.org/package/base-4.20.0.1/docs/Prelude.html#v:-60--36--62- https://hackage.haskell.org/package/base-4.20.0.1/docs/Prelu...
- fer 2y ago> other languages do not Which ones? I think there's always some way to isolate, even if ugly.
- instig007 2y ago> Which ones? I think there's always some way to isolate, even if ugly. Almost all of them? You need referential transparency (via laziness) too, otherwise your attempt at isolation will break at the first binding expression in a local scope for future processing elsewhere: ... let arg = processData <$> ioAction in ... Do you want to wrap-and-call-later all of these cases into lambdas by hand? :)
- gpderetta 2y ago> the article complains that async/await 'infects' all the code that touches it and forces the callers to use async/await too. But isn't the same true with go channels ? I'm not familiar with go, but I don't think so: stackful coroutines abstract better than the stackless kind.
- whoisthemachine 2y agoYep in some way the programmer needs to express that the routine will have to _continue_ when IO completes (which will necessarily go up to the top of the stack in some way, unless you don't care about the result of the IO operation), or the runtime needs to block until IO completes.
- fwip 2y agoIn a big Go application, most of the time you're not writing code that runs in the "main" thread. If you're writing a UI, you put the UI code in its own goroutine, and pass messages to it. If you're writing a server, most of your code will be in your endpoint handlers, which run as their own goroutines. In >95% of your code, it's fine to just write `foo_val <- foo_chan`, without spawning a goroutine. From a pragmatic standpoint, it's not really different from `foo_val = expensive_foo_calculation()`. This block of code is waiting for something else to finish, and the Go runtime is smart enough to decide whether or not this thread should be parked until that result is ready. And, as a bonus, `foo_val = expensive_foo_calculation()` looks the same, even if the implementation launches 10 cpu-bound goroutines and reads from 30 files to do the work.