- cross-posted to:
- [email protected]
- cross-posted to:
- [email protected]
I’ve had just this case. Wanted to use a particular crate that uses async and it’s forcing me to do lots of async things I’m unfamiliar with. I resent it a little, especially for a program that I’m fairly sure will not require concurrency of this sort.
At the same time, maybe I’ll get used to async rust if I use it enough. But so far I’m not having a lot of fun with it.
It’s actually not that hard to use async libraries in sync context. I rarely need that but if I do, I just pull in an executor and write a little extension trait for futures that lets me call .block() instead of .await.
I would really wish that the async ecosystem would not be based around runtimes, but would separate runtimes from async libraries. Like let me do file IO async without having to choose between async-std, Tokio, or whatnot for that.
Practically speaking, you don’t have to.
Your executor of choice should be doing
tokio
compat for you, one way or another, so you don’t have to worry about it (e.g. async-global-executor with thetokio
feature).async-std
is dead.I think it’s something being worked on. Unfortunately I can’t recall the details offhand.
Next Day Edit: Sorry. Forgot to use my Canadian Aboriginal syllabics again. Because apparently it’s too hard to admit HTML-sanitizing source markdown was wrong!
One thing that irks me in these articles is gauging the opinion of the “Rust community” through Reddit/HN/Lemmy😉/blogs… etc. I don’t think I’d be way off the mark when I say that these platforms mostly collectively reflect the thoughts of junior Rustaceans, or non-Rustaceans experimenting with Rust, with the latter being the loudest, especially if they are struggling with it!
And I disagree with the argument that poor standard library support is the major issue, although I myself had that thought before. It’s definitely current lack of language features that do introduce some annoyances. I do agree however that implicit coloring is not the answer (or an answer I want to ever see).
Take this simple code I was writing today. Ideally, I would have liked to write it in functional style:
async fn some_fn(&self) -> OptionᐸMyResᐸVecᐸu8ᐳᐳᐳ { (bool_cond).then(|| async { // ... // res_op1().await?; // res_op2().await?; // ... Ok(bytes) }) }
But this of course doesn’t work because of the opaque type of the async block. Is that a serious hurdle? Obviously, it’s not:
async fn some_fn(&self) -> OptionᐸMyResᐸVecᐸu8ᐳᐳᐳ { if !bool_cond { return None; } let res = || async { // ... // res_op1()?; // res_op2()?; // ... Ok(bytes) }; Some(res().await) }
And done. A productive Rustacean is hardly wasting time on this.
Okay,
bool::then()
is not the best example. I’m just show-casing that it’s current language limitations, not stdlib ones, that are behind the odd async annoyance encountered. And the solution, I would argue, does not have to come in the form of implicit coloring.Yeah, “async is a niche requirement” has long seemed weird to me. Most programs with any degree of interactivity quickly come to a point where they want more than one thing to be happening at once, and they spend some time waiting on external inputs – whether those are network packets or USB events or timers.
Purely synchronous code only suffices for that narrow and most boring category of programs that know all their inputs up-front and don’t accept any other inputs or interactions at all.
Well, CLI tools fall under that category, and they’re not exactly rare to be written in Rust these days.
My most recent one had to use tokio anyways due to a library crate that used it (rtnetlink). Luckily, I don’t mind that at all.