Remix.run Logo
neonsunset 10 hours ago

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.

shakna 8 hours ago | parent [-]

Different languages have different syntax, but most do not have a separate syntax inside themselves. A function is generally a function. They do adopt various structures - but those are structures, not syntax. I'm not sure you've understood that was my point.

neonsunset 7 hours ago | parent [-]

[edited out the swipe]

Do-notation-like 'await' is not for calling functions, it is for acting on their return values - to suspend the execution flow until the task completes.

shakna 6 hours ago | parent [-]

I've written patches for F#. I do know what the hell I'm talking about.

However, the compiler does not, has never, required that it does things via a different syntax. In fact, in the early branches before that was adopted, it didn't! The same behaviour was seen in those branches. This behaviour you expect, was never something that had to be. It was something chosen to simplify the needs of the optimiser, and in fact cut the size of code required in half. It was to reduce the amount of code needed to be maintained by the core team. And so 1087 [1] was accepted.

So perhaps you might need to read more into the process of the why and how async was introduced into C# and F#. It was a maintenance team problem. It was a pragmatic approach for them - not something that was the only way that this became a possibility.

As said, in the original branch for using tasks...

> Having two different but similar ways of creating asynchronous computations would add some cognitive overhead (even now there are times when I am indecisive between using async or mailbox for certain parallelism/concurrency scenarios). [0]

[0] https://github.com/fsharp/fslang-suggestions/issues/581

[1] https://github.com/fsharp/fslang-design/blob/main/FSharp-6.0...

neonsunset 6 hours ago | parent [-]

Alright, I stand corrected.

However, this is where our opinions differ. I like task CE (and taskSeq for that matter too). It serves as a good and performant default. It's great to be able to choose the exact behavior of asynchronous code when task CE does not fit.