Explicit yield / resume, like Lua? Full-on CPS?
Explicit yield / resume, like Lua? Full-on CPS?
Every time I bring this up there are people who jump in with excuses for why Rust can't do something similar. But these are either (1) historical accidents in the sense of implementing goroutines would've broken existing code [fair], or (2) excuses. Go's approach is much harder to get right, and much more pervasive in the impact on the language. But when it's done well, it's really smooth to use.
I use Rust as my daily driver because I want the safety guarantees that Rust gives, and cargo is pretty nice. But every time I need to do something highly concurrent, I wish I was working in Go...
It's almost as if there's two fundamentally different types of functions that people might want to declare, necessitating two function colors.
Go is a language that is primarily used for async programming, so the design of having everything async makes sense. Rust is a language that is primarily used for sync programming, async programming is catered for but it's not the focus of the language. So having everything be async doesn't make any sense at all.
Since any function can get indefinitely stuck in a system call, the main difference between "sync" and "async" isn't whether you can pause execution, it's who can pause execution. And the main downside to the more flexible option is that it requires extra overhead in how the stack gets allocated.
But why should the flexible/inflexible choice be made on a per-function basis? I feel like I'm manually annotating which functions will inline, except worse because certain combinations won't compile. Instead, how about having the compiler figure it out on a per-call basis?
The way the async feature works in Rust is that the asynchronous function is just a syntax sugar that gets desugared into a state machine struct during compilation. The way this state machine works is similar to how one could achieve async in a language like C. It's unfair to dismiss everything as excuses given that the fundamental aim of the language is different.
In Rust async functions are not really colored because again - the async function is just a syntax sugar for a struct you can create and use in a sync context. The colors analogy is only really applicable in a language like JavaScript, where there's no way to poll an async function in a sync context.
FYI you can't poll an async result in a sync context in Rust, either.
Sure you can. Async runtimes in Rust are written in Rust, that's exactly what they do.
First, it would be a huge undertaking. That in itself is a huge time/resource burden.
Second, it would add overhead to any non-async function call. Because async introduces branching on every function invocation, it would make the resulting assembly even harder to understand. This strongly goes against the zero overhead/ zero cost abstraction idea of Rust.
By the same measure, Go could technically remove (almost) all GC, add some kind of borrowing mechanism and steal Rust's thunder.