Rust lacks them, but so far that seems to me to be a shortcoming in Rust
I think it’s a benefit. In Rust, you have two options:
panic - usually catchable with catch_unwind() (some types are not), and should be used rarely, this isn’t try/catch
result - return a value that indicates an error, like a super fancy errno, but with monad semantics that force you to acknowledge it
This is good for a few reasons:
“normal” errors are explicit in the return type; if a function doesn’t return a result, it can’t return errors
outliers aren’t accidentally handled - since you shouldn’t be catching panics, you can rely on them to completely crash
no need to instrument the code with unwinding logic in case something throws an exception, meaning a more efficient runtime
Where do the call stacks for the different async tasks live and how are they allocated?
The async runtime handles that. You’d need to look at the specific implementation to see how they handle it, the standard library only provides tools for dealing with async.
My understanding is that it works kind of like a generator, so any await call yields to the runtime, which resumes another generator. That’s an over simplification, but hopefully it’s close enough.
Call/cc
I think this is basically just the general idea of a generator, but the caller chooses where the yield yields to.
I agree with the criticisms of call/cc, and I think it’s much clearer to just use coroutines (of which generators are a special case) and otherwise linear control flow instead of messing about with continuations. IMO, the only people that should mess with continuations are lower level engineers, like driver authors, compiler devs, and async lib devs. Regular devs will just create more problems for themselves.
I think it’s a benefit. In Rust, you have two options:
catch_unwind()
(some types are not), and should be used rarely, this isn’t try/catchThis is good for a few reasons:
The async runtime handles that. You’d need to look at the specific implementation to see how they handle it, the standard library only provides tools for dealing with async.
My understanding is that it works kind of like a generator, so any await call yields to the runtime, which resumes another generator. That’s an over simplification, but hopefully it’s close enough.
I think this is basically just the general idea of a generator, but the caller chooses where the yield yields to.
I agree with the criticisms of call/cc, and I think it’s much clearer to just use coroutines (of which generators are a special case) and otherwise linear control flow instead of messing about with continuations. IMO, the only people that should mess with continuations are lower level engineers, like driver authors, compiler devs, and async lib devs. Regular devs will just create more problems for themselves.