I am suspicious that Async, slowly taking over the library ecosystems, will be what drives me away from Rust. Over the past year, it's taken over embedded. I was previously worried about excessive use of generics, but this was, gradually over the past ~2 years replaced with Async.
The std-lib HTTP ecosystem has already gone almost full-async. I was able to spin up a simple web server without it using the rouille library recently. I chose this one because it was one of two options that wasn't Async.
I think I may be the only person who A: Enjoys rust for embedded targets (Eg Cortex-M), but doesn't enjoy Async. The easy path is to go with the flow and embrace Async in those domains (Embedded, web backends). I say: No. Threads, interrupts, DMA, etc are easier to write and maintain, and critically, don't split code into two flavors. You don't just add an Async library to your program: It attempts to take your program over. That is the dealbreaker.
> The easy path is to go with the flow and embrace Async in those domains (Embedded, web backends). I say: No.
Why are you making a principle of not using async though? It's just one particular feature of the language, there's nothing wrong in not being particularly enthusiast about it, but entirely refusing to use it sounds really weird to me.
Every JavaScript junior use async right now, it's not as it is was a particularly difficult programming paradigm to learn. Sure async in rust is a bit more complicated than in JS due to the fact it's lower level, but it's not worse than anything else in Rust!
> Threads, interrupts, DMA, etc are easier to write and maintain,
Not really. I've no doubt that you master them better, but there's no reason to think you won't be able to be as proficient with async. And in fact, async is just strictly more powerful than sync code: you can do exactly what you're doing right now (just write await), plus you get a few features for free (concurrency, cancelation). There's a reason why it's popular actually!
> and critically, don't split code into two flavors
In practice, there isn't either. No if you're writing an application, it's only when you're writing a library and you want to support explicitly the use case of people like you that have moral issues with async.
> It can be frustrating to: People who target wasm
Having worked with wasm, I couldn't disagree more. Maybe it's been fixed now and we have proper threading support in wasm, but for a long time every thread related function of wasm-unknown-unknown panicked because the function was unimplemented whereas async code just worked.
> People who target embedded
I don't have any embedded experience in Rust so I don't have an opinion, but at the same time I fail to see how it can be frustrating in that space: if you're targeting no-std you cannot use a dependency that isn't no-std itself so you're unlikely to be bothered by non-embeded use of async. Now if async take over embedded, that's different but at the same time it means it's probably not “frustrating” to the majority of people but in fact helpful.
> And superfluous to:
This is a very poor metric, I've never used once any if the math primitives in the std lib in 9 years of Rust, almost never Unicode parts of the std, barely used atomic and never inline assembly, that doesn't mean these features do not belong to Rust and I have no issues with them being there even though they are superfluous to me. The key difference is that I don't have any ideological detestation of them…
A bit late to reply, but if you see this know that you made some good points. Detesting it is probably a bit much, but I do find the pattern cumbersome. Do you use tokio in wasm? I haven't, but I've seen issues for wasm support closed because of tokio. That could have been an excuse. Again in embedded what I run into is that embassy is the standard executor, and is useful, but so many crates bring in tokio when they don't really need to that they are poisoned for embedded use. Lastly it isn't just being superfluous, it is a dozen or more crates bringing download size and attack surface that don't solve any problem I ever actually have, or mostly any problem the crate author had. So really what you helped me realize is that it isn't async/await I dislike at all, it is just tokio being the defacto implementation of it.
I don't think tokio itself is going to be the issue for wasm or embedded, but if the crate you're importing uses tokio it usually means it's expecting to have access to an OS with file and network access, none of which is going to work in wasm or embedded in the first place.
But I agree with you on the fact that Rust ecosystem (the part of the ecosystem that uses std at least) is tied to tokio is not a good situation. In theory we could have crates being agnostic about the executor, as they aren't supposed to execute anything, just expose the futures and the top level crate is the one driving the execution, but AFAIK the way tokio is designed currently makes it impossible to separate the concerns. The Rust team would like to change that, but it's not trivial and it would require collaboration from the tokio team, which is not granted.
The std-lib HTTP ecosystem has already gone almost full-async. I was able to spin up a simple web server without it using the rouille library recently. I chose this one because it was one of two options that wasn't Async.
I think I may be the only person who A: Enjoys rust for embedded targets (Eg Cortex-M), but doesn't enjoy Async. The easy path is to go with the flow and embrace Async in those domains (Embedded, web backends). I say: No. Threads, interrupts, DMA, etc are easier to write and maintain, and critically, don't split code into two flavors. You don't just add an Async library to your program: It attempts to take your program over. That is the dealbreaker.