←back to thread

452 points birdculture | 1 comments | | HN request time: 0.219s | source
Show context
Havoc ◴[] No.43979116[source]
I thought it was quite manageable at beginner level…though I haven’t dived into async which I gather is a whole different level of pain
replies(1): >>43979133 #
echelon ◴[] No.43979133[source]
Async and the "function color" "problem" fall away if your entire app is in an async runtime.

Almost 90% of the Rust I write these days is async. I avoid non-async / blocking libraries where possible.

I think this whole issue is overblown.

replies(6): >>43979257 #>>43979273 #>>43979433 #>>43979524 #>>43981881 #>>43986031 #
bigstrat2003 ◴[] No.43979433[source]
"Just write everything async" is not remotely a good solution to the problem. Not everything needs to be async (in fact most things don't), and it's much harder to reason about async code. The issue is very much not overblown.
replies(1): >>43979650 #
Salgat ◴[] No.43979650[source]
Why is async code harder to reason about? I've been using it in C# and the entire point is that it lets you write callbacks in a way that appears nearly identical to synchronous code. If you dive into concurrency (which is a separate thing but can be utilized with async code, such as joining multiple futures at the same time), that parts hard whether you're doing it with async or with explicit threads.
replies(3): >>43980094 #>>43980325 #>>43982797 #
Const-me ◴[] No.43980325[source]
> I've been using it in C#

One reason why async-await is trivial in .NET is garbage collector. C# rewrites async functions into a state machine, typically heap allocated. Garbage collector automagically manages lifetimes of method arguments and local variables. When awaiting async functions from other async functions, the runtime does that for multiple async frames at once but it’s fine with that, just a normal object graph. Another reason, the runtime support for all that stuff is integrated into the language, standard library, and most other parts of the ecosystem.

Rust is very different. Concurrency runtime is not part of the language, the standard library defined bare minimum, essentially just the APIs. The concurrency runtime is implemented by “Tokio” external library. Rust doesn’t have a GC; instead, it has a borrow checker who insists on exactly one owner of every object at all times, makes all memory allocations explicit, and exposed all these details to programmer in the type system.

These factors make async Rust even harder to use than normal Rust.

replies(1): >>43984061 #
echelon ◴[] No.43984061[source]
None of this is scary.

> The concurrency runtime is implemented by “Tokio” external library.

Scare quotes around Tokio?

You can't use Rails without Rails or Django without Django.

The reason Rust keeps this externally is because they didn't want to bake premature decisions into the language. Like PHP's eternally backwards string library functions or Python's bloated "batteries included" standard library chock full of four different XML libraries and other cruft.

> instead, it has a borrow checker who insists on exactly one owner of every object at all times, makes all memory allocations explicit, and exposed all these details to programmer in the type system

Table stakes. Everyone knows this. It isn't hard or scary, it just takes a little bit of getting used to. Like a student learning programming for the first time. It's not even that hard. Anyone can learn it.

It's funny people complain about something so easy. After you learn to ride the bike, you don't complain about learning to ride the bike anymore.

> Rust is very different.

Oh no!

Seriously this is 2025. I can write async Rust without breaking a sweat. This is all being written by people who don't touch the language.

Rust is not hard. Stop this ridiculous meme. It's quite an easy language once you sit down and learn it.

replies(1): >>43992400 #
1. guappa ◴[] No.43992400[source]
> I can write async Rust without breaking a sweat

The difficult part comes when you try to do so "correctly".