Are there any efforts to overhaul or completely rethink this?
Are there any efforts to overhaul or completely rethink this?
Algebraic effects would solve this, but I don’t know any language other than OCaml that is working on that approach.
You can convert colors simply but only one way, and practically that works, functional core imperative shell, etc.
* The async runtime and async functions are decomposed but tightly coupled. That means while you could swap out runtimes, a crate built against one runtime can’t generally be used with another unless explicitly designed to support multiple. I believe C++ has a similar problem but no other major language I’m aware of has this problem - that’s typically because there’s only a single runtime and it’s embedded in the language. Things like timers and I/O are not interoperable because the API you use has to be for the runtime you’re running under. I believe there’s work ongoing to try to remedy this although in practice I think that’s difficult (eg what if you’re using a crate relying on epoll-based APIs but the runtime is io_uring).
* async in traits. I believe that’s coming this year although the extra boxing it forces to make that work makes that not something 0-cost you can adopt in a super hot path.
* async requires pinned types which makes things very complex to manage and is a uniquely Rust concept (in fact I read a conceptually better alternative proposal for how to have solved the pin/unpin problem on HN not too long ago, but that ship has long sailed I fear).
* The borrow checker doesn’t know if your async function is running on a work stealing runtime or not which means there’s a lot more hoop jumping via unsafe if you want optimal performance.
* async functions are lazy and require polling before they do anything. That can be a bit surprising and require weird patterns.
Don’t get me wrong. The effing-mad crate is a fantastic demonstration of the power of algebraic effects to comprehensively solve coloring issues (async, failability, etc). But I think there’s stuff with runtime interop that’s also important. I don’t think anyone is yet seriously tackling improving the borrow checker for thread per core async.
[1]: https://www.unison-lang.org/
[2]: https://www.unison-lang.org/learn/language-reference/abiliti...
In general I’ve noticed that there are a lot of code generation modules that can generate very cryptic error messages if you stay clear of their happy paths.
Any kind of shared resource is a tedious experience, that's basically it's selling point.
It is frustrating becasue if you go look for help, people are always condescending about global shared resources like that but there really isn't a better way.
Adding it to your project probably increases the average code quality:)
tl;dr: You can have different (nicer to program) abstractions, but you can't have them in the same language you use to write firmware for a $10 electronic device, or Linux drivers, and we already have languages like Go and Javascript whereas we did not have a safer alternative to C++.