▲ | shakna 12 hours ago | ||||||||||||||||||||||||||||||||||
> It is bespoke and async-specific. There is nothing wrong with it but it's necessary to acknowledge this limitation. I would disagree. If you need to have a bespoke set of syntax, then something is not integrated where it should be. The language design should not be such that you are writing things differently, depending on the paradigm that you're handling. That's not something that occurs in every language, so it isn't essential that it exists. We can acknowledge the differences in a way that alerts the programmer, without forcing the programmer to switch syntaxes back and forth when moving between the paradigms. async/await is one method, Promises another, etc. A different syntax is a much, much higher cognitive load. | |||||||||||||||||||||||||||||||||||
▲ | Vetch 9 hours ago | parent | next [-] | ||||||||||||||||||||||||||||||||||
F#'s computation expressions are closely related to Haskell's monads + do-notation combo, CEs are both more limited than Haskell's approach to monads (from a type expressibility perspective) and more expressive than pure monads (from a modeling perspective, can model a general class of computational structures beyond monads; CE's also share F#'s syntax, with extensible semantics). This notation can be advantageous and clarifying when used in the right places. It has advantages over C#'s async from a flexibility/extensibility perspective and also provides more options in orchestrating more complex control flow across async computations. C#'s approach is more streamlined if you only care about using async according to how Tasks are designed (which still enable a quite broad scope) and don't need the flexibility for other computational patterns. Simple things like the maybe and either monad are often clearer in this notation. Complex things like alternatives to async (such as CSP derived message passing concurrency), continuations, parser combinators, non-determinism, algebraic effects and dependency tracked incremental computations are naturally modeled with this same machinery, with CE notation being a kind of super helpful DSL builder that makes certain complex computations easier to express in a sequenced manner. If the custom syntax was only for async you'd have a point, but the general power of the framework make it the more preferable approach by far, in my opinion. | |||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||
▲ | neonsunset 10 hours ago | parent | prev [-] | ||||||||||||||||||||||||||||||||||
I cannot make sense of this reply. Different languages have different syntax. Support of asynchronous code and of its composition is central to C#, which is why it does it via async/await and Task<T> (and other Task-shaped types). Many other languages considered this important enough to adopt a similar structure to their own rendition of concurrency primitives, inspired by C# either directly or indirectly. Feel free to take issue with the designers of these languages if you have to. F#, where async originates from, just happens to be more "powerful" as befits an FP language, where resumable code and CEs enable expressing async in a more generalized fashion. I'm not sold on idea that C# needs CEs. It already has sufficient complexity and good balance of expressiveness. | |||||||||||||||||||||||||||||||||||
|