* 3 fibers - each fetches from remote storage, local storage and in-memory cache.
* Race them, kill the two slowest and give me the result.
* Free the resources safely including if any of the connections fails for an unforeseen reason.
That's a few lines in ZIO. Pain to get working properly in Java, Rust, Go, C++ at least.
https://www.learnrxjs.io/learn-rxjs/operators/combination/ra...
Error handling and deferring for resource closure work just fine.
Sure you could say "but the compiler doesn't guarantee it". But that's not much of a point if it's not a real problem in practice.
But that's exactly what OP was talking about. Maybe for you that doesn't mean Go fails here, but for (us) Scala developers it definitely feel like Go fails us. We want a language that fails at compiletime in as many cases as possible.
> But that's not much of a point if it's not a real problem in practice.
Maybe not for you. For me it is!
But it's the difference between whether this statement is objective, or subjective.
> is the best concurrency library on any platform
I understand why people who like monadic constructs don't like it though.
I agree algebraic data types could improve this. I don't think monadic result types or exceptions would be an improvement.
I do not want to wait for the three fibers to finish. I want the whole process to stop the minute any of them have returned i.e. get me my data as quick as possible no matter its source.
You wait for the first result using i.e. a shared result channel, then you cancel the context.
It's why almost anything outside the BEAM can't make that claim.
I guess a merge of Scala as the language (because honestly, Erlang & co suck) and BEAM as the platform would be awesome!
(Disclaimer: I haven't used Gleam, I just know it exists.)
Unfortunately, all libraries that abstract concurrency on an application-level break the ability to get meaningful stack traces. At least all the ones I know of, including ZIO, Akka, Monix, plain Futures, etc. I know that there is tooling to counteract that (such as the abstractions used in distributed tracing), but that's again on the language level.
In my experience, for all but the most advanced applications, the debuggability advantages of using linear code outweigh the performance advantages gained by abstracting over execution contexts. Thus, I would posit that concurrency is best dealt with on the platform, not the language level, especially when starting a project.
Of course there are some situations where a library can make some concurrency task appear trivial, but as long as there is no good tooling, the time saved using beautiful abstractions tends to be paid back 5-fold when those abstraction break (which they often do as an application grows).
This is completely false. Years ago we (7mind) added async stack traces to ZIO. Now both Cats and ZIO support them.