One thing that most languages are lacking is expressing lazy return values. -> await f1() + await f2() and to express this concurently requres manually handing of futures.
replies(3):
await Join(f1(), f2())
Although more realistically Promise1 = f1(); Promise2 = f2();
await Join(Promise1, Promise2);
But also, futures are the expression of lazy values so I'm not sure what else you'd be asking for. Promise1 = f1(); Promise2 = f2();
v1,v2 = await Join(Promise1, Promise2);
return v1 + v2
I think this is just too much of synthactic noise.On the other hand, it is necessary becase some of underlying async calls can be order dependend.
for example
await sock.rec(1) == 'A' && await sock.rec(1) == 'B'
checks that first received socket byte is A and second is B. This is clearly order dependant that can't be executed concurrently out of order. SumAsync(F1(),f2());
Buy it's kind of intractable, isn't it? Your language has to assume order dependency or independency and specify the other. Most seem to stick with lexical ordering implies execution order.I think some use curly brace scoping to break up dependency. I want to say kotlin does something like this.
This is why they say async is a viral pattern but IMO that's because you're adding specificity and function coloring is necessary and good.