4 ms·
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
by Havoc 1y ago
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
- echelon 1y agoAsync 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.
- spion 1y agoHow are async closures / closure types, especially WRT future pinning?
- echelon 1y agoWhile I'd like to have it, it doesn't stop me from writing a great deal of production code without those niceties. When it came time for me to undo all the async-trait library hack stuff I wrote after the feature landed in stable, I realized I wasn't really held back by not having it.
- mplanchard 1y agoAsync closures landed in stable recently and have been a nice QoL improvement, although I had gotten used to working around their absence well enough previously that they haven’t been revolutionary yet from the like “enabling new architectural patterns” perspective or anything like that. I very rarely have to care about future pinning, mostly just to call the pin macro when working with streams sometimes.
- sodality2 1y agoThat’s not a solution to the coloring problem any more than making everything red was in 2015 (ie, all the tradeoffs mentioned in the article [0] still apply). [0]: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
- bigstrat2003 1y ago"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.
- Salgat 1y agoWhy 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.
- School-Cotton 1y ago> Why is async code harder to reason about? I don't know about C#, but at least in Rust, one reason is that normal (non-async) functions have the property that they will run until they return, they panic, or the program terminates. I.e. once you enter a function it will run to completion unless it runs "forever" or something unusual happens. This is not the case with async functions -- the code calling the async function can just drop the future it corresponds to, causing it to disappear into the ether and never be polled again.
- Const-me 1y ago> 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.
- lucasyvas 1y agoIt’s completely overblown. Almost every language with async has the same “problem”. I’m not calling this the pinnacle of async design, but it’s extremely familiar and is pretty good now. I also prefer to write as much async as possible.
- echelon 1y agoThe "function color is a problem" people invented a construct that amplifies the seriousness. It's not really a big deal.
- Measter 1y agoMy biggest issue with the whole "function colour" thing is that many functions have different colours. Like, these two: fn foo() -> String fn bar() -> Result<String, Error> I can't just treat `bar` the same as `foo` because it doesn't give me a String, it might have failed to give me a String. So I need to give it special handling to get a String. async fn qux() -> String This also doesn't give me a String. It gives me a thing that can give me a String (an `impl Future<Output=String>`, to be more specific), and I need to give it special handling to get a String. All of these function have different colours, and I don't really see why it's suddenly a big issue for `qux` when it wasn't for `bar`.
- echelon 1y agoExcellent retort!
- kaoD 1y agoAsync's issue is not coloring. It's introducing issues that just don't exist in sync code like pinning, synchronization, future lifetimes... Coloring just exacerbates the issues because it's viral, not because coloring itself is an issue.
- notnullorvoid 1y agoAgreed. Function coloring is a solution (not a problem), one that's better than the alternatives. The "function coloring problem" people are harming entire ecosystems. In JS for example there are very popular frameworks thay choose to wrap async in sync execution by throwing when encountering async values and re-running parts of the program when the values resolve. The crazy part with these solutions trying to remove coloring, is they don't, they hide it (poorly). So instead of knowing what parts of a program are async you have no idea.