var data1 = service1.GetData();
var data2 = service2.GetAnotherData();
var aggregate1 = Aggregate(await data1);
var result = Handle(await aggregate1, await data2);
No need to deal with writing three lines per each operation to just schedule it in a "fork" way like in Java. In "colorless" (which is always a lie) async runtimes you have to go out of your way to make it concurrent. Perhaps Erlang process isn't coarse grained abstraction as you say, but there are multiple aspects that make Erlang problematic. And again, I will not tire of repeating it - the article about function coloring is actively harmful to the industry and is leading hundreds of developers with concurrency knowledge gaps assume that they need to avoid Task/Future-based code like plague when it is actually the best abstraction we have today for massively concurrent processes (if it was badly designed in whatever language of your choice - sorry).
In addition, because Task<T> is a thread-safe object in C#, you can apply all kinds of transformations and data chaining with LINQ on collections/sequences of those, or even together with parallel LINQ and tasks at the same time. Your simple average code will easily scale to all CPU cores if it does not have interdependencies/contention (a lot of LOB codebases don't, it's all straight line up to a DB or a third-party call(s)).
And last but not least, all BEAM-based languages are comparatively slow (hard performance ceiling is always imposed if you don't pay with static typing and full JIT/AOT) and unfortunately suffer from high heap footprint, even compared to the more throughput-focused GC modes in .NET and GC implementations in JVM. But no, developers are insistent on parroting quotes said 10 to 15 years ago instead of at least attempting to assess technologies on their merits of today.
No, colourless isn't a lie. Erlang doesn't have two types of function (sync and async). C#/Python now do. As a function/method implementer in those languages, for every single function implementation, I am faced with the following:
1. My function has to be async, because someone, somewhere, in the call chain of functions I want to invoke, decided to make their function async. So I have to deal with the downsides (lower performance, debugging complexity) whether I need the upsides or not.
2. I need to decide whether to make my function async because the decision hasn't been taken out my hands somewhere down the call stack. If I'm writing a library function that means I'm now having to judge how callers will use my function. If I decide async, then I've imposed constraints on the caller as per #1.
3. I need to implement sync & async versions of my function so as not to constrain the choices of my callers.
That emerges because of (1) the asymmetric constraint imposed by async/await and (2) the requirement for function implementers to make the decision, not callers. A sync function can't call an async one. That's the basis of colouring. It's not a lie.
the article about function coloring is actively harmful to the industry
No, the article about colouring very clearly explains the asymmetric nature of sync/async and the limitation it imposes. Its use of colour as a metaphor very clearly illustrates the issue. Sure, there's a risk that some people won't fully read and understand it - and then just parrot "yeah, coloured is bad". That's not the fault of the article though.
There's nothing inherently wrong with Futures as a concurrency construct: it's essentially enabling cooperative multitasking. The issue is that async/await as an implementation causes codebase bifurcation.
all BEAM-based languages are comparatively slow
Emphasis on "comparative". I don't disagree that in certain dimensions - notably raw compute performance and memory usage - BEAM languages are comfortably down the benchmark tables compared to C#. That doesn't always translate to real world practicality though (and even throughput is getting better given the active JIT work).
developers are insistent on parroting quotes said 10 to 15 years ago instead of at least attempting to assess technologies on their merits of today.
Futures have merit per above. Async/await brings syntactic convenience which, in isolation, is an improvement. But with it comes significant cost. Cost that isn't there with green threads and isn't intrinsic to Futures either. You can't just sweep those limitations under the carpet by promulgating the hubris that the arguments are old.
Comments
In C#, interleaving various tasks is as easy as
No need to deal with writing three lines per each operation to just schedule it in a "fork" way like in Java. In "colorless" (which is always a lie) async runtimes you have to go out of your way to make it concurrent. Perhaps Erlang process isn't coarse grained abstraction as you say, but there are multiple aspects that make Erlang problematic. And again, I will not tire of repeating it - the article about function coloring is actively harmful to the industry and is leading hundreds of developers with concurrency knowledge gaps assume that they need to avoid Task/Future-based code like plague when it is actually the best abstraction we have today for massively concurrent processes (if it was badly designed in whatever language of your choice - sorry).In addition, because Task<T> is a thread-safe object in C#, you can apply all kinds of transformations and data chaining with LINQ on collections/sequences of those, or even together with parallel LINQ and tasks at the same time. Your simple average code will easily scale to all CPU cores if it does not have interdependencies/contention (a lot of LOB codebases don't, it's all straight line up to a DB or a third-party call(s)).
And last but not least, all BEAM-based languages are comparatively slow (hard performance ceiling is always imposed if you don't pay with static typing and full JIT/AOT) and unfortunately suffer from high heap footprint, even compared to the more throughput-focused GC modes in .NET and GC implementations in JVM. But no, developers are insistent on parroting quotes said 10 to 15 years ago instead of at least attempting to assess technologies on their merits of today.
No, colourless isn't a lie. Erlang doesn't have two types of function (sync and async). C#/Python now do. As a function/method implementer in those languages, for every single function implementation, I am faced with the following:
1. My function has to be async, because someone, somewhere, in the call chain of functions I want to invoke, decided to make their function async. So I have to deal with the downsides (lower performance, debugging complexity) whether I need the upsides or not.
2. I need to decide whether to make my function async because the decision hasn't been taken out my hands somewhere down the call stack. If I'm writing a library function that means I'm now having to judge how callers will use my function. If I decide async, then I've imposed constraints on the caller as per #1.
3. I need to implement sync & async versions of my function so as not to constrain the choices of my callers.
That emerges because of (1) the asymmetric constraint imposed by async/await and (2) the requirement for function implementers to make the decision, not callers. A sync function can't call an async one. That's the basis of colouring. It's not a lie.
No, the article about colouring very clearly explains the asymmetric nature of sync/async and the limitation it imposes. Its use of colour as a metaphor very clearly illustrates the issue. Sure, there's a risk that some people won't fully read and understand it - and then just parrot "yeah, coloured is bad". That's not the fault of the article though.
There's nothing inherently wrong with Futures as a concurrency construct: it's essentially enabling cooperative multitasking. The issue is that async/await as an implementation causes codebase bifurcation.
Emphasis on "comparative". I don't disagree that in certain dimensions - notably raw compute performance and memory usage - BEAM languages are comfortably down the benchmark tables compared to C#. That doesn't always translate to real world practicality though (and even throughput is getting better given the active JIT work).
Futures have merit per above. Async/await brings syntactic convenience which, in isolation, is an improvement. But with it comes significant cost. Cost that isn't there with green threads and isn't intrinsic to Futures either. You can't just sweep those limitations under the carpet by promulgating the hubris that the arguments are old.
Do you have experience with C#? If yes, how much?