4 ms·
Interesting analogy, seems like many of these binary choices cause divides. My point about the design being mistake is the way you need to be explicit in invok
by whizzter 6y ago
Interesting analogy, seems like many of these binary choices cause divides.
My point about the design being mistake is the way you need to be explicit in invoking with await and the often harmful side-effect of forgetting the await expression (that in practice becomes a code-path fork that can become tricky to debug if the awaited function is a void function with no unexpected values coming out of the missed await expression).
For JavaScript the dynamic type-system really leaves no choice since the caller has no information about the behaviour of the callee, so await for these dynamic languages is kinda unavoidable (unless the entire language is green-threaded thatis).
For Rust and C# (and probably others) the compiler knows about this in advance so the "await" expression just adds an extra layer of work for the developer (that is also error prone).
There is little reason that for example the C# compiler couldn't have auto-inserted the await for all Task<> returning functions inside every (async) marked function and instead had a (direct) operator for the FEW cases where a developer really wants to handle the Task<> object manually instead of just awaiting it (C# is quite pragmatic in many other cases so the little loss of direct developer control would have been far outweighted by better symmetry and less ceremony).
Practical? Definitely, the Zig language seems to even handle this entirely under the hood by it's compile-time functionality. So for a developer the red-blue distinction is mostly something handler by the compiler despite not affecting the runtime more than some extra code i guess?
- kannanvijayan 6y agoAfter some thought, I think I basically agree with that main point. I've actually been dipping my feet heavily into async programming in rust (personal stuff), and async programming in typescript (work stuff) after about a decade mostly doing C++ stuff (previous work). The challenges and confusions you mention are pretty fresh in my mind. Maybe switching the default semantic behaviour over to recognize the async type signatures and implementing this sort of default syntax transform is the better way to go. I wonder if it might cause problems with generic code - where a return type for some otherwise non-async function happens to "become a future" due to type-specialization, turning the function async? But maybe that's not an issue because the call-specialization behaviour just transitively applies to all the callers up the chain, same as any other specialization. Beyond that, I think this whole conversation has a hard time moving forward before we get a good industry understanding of high-level concurrency structures in practice. So far the major one people fixate on is "actors", which usually reduces to "stream processor".. which is a nice construct but by itself not enough to build complete programs out of. You need an entire structural framework to talk about what produces the things the stream processes. Sometimes that'll be other streams, sometimes that'll be static, sometimes that'll be some collection of random event sources, some of which are direct and some of which are indirect. Then you need ways of talking about how those producers relate to each other, and _some_ way of identifying and preserving global / regional / local invariants. Error handling is a nightmare. I haven't yet found any good vocabulary to talk about shutdown order for tasks and error handling in, how to express it clearly in the program intent, and how to make sure that intent doesn't rot over time. It's all ad-hoc promises and hooks and callbacks wiring up _this_ event to _that_ thing.. accompanied by small or large comments along with the hope that your fellow developer is cleverer than you and can actually figure out the intent from just the text of the code. After we get a few good examples of those sorts of things, it'll be easier to go back and discuss syntax and semantics, and we'll have a reference set of designs/patterns to check against and make sure we can express cleanly.