I want to note here that throughout the internet and HN there is this ongoing wisdom that although Rust is very useful, valuable etc writing code in it is very hard because it constantly feels like you're wrestling the compiler.<p>Well, maybe there is some truth to it, but I want to say that having started learning Rust in 2022, I found it's multi-threadedness model very refreshing. I thought it was such a delight to write code in, and personally loved it at least one order of magnitude than Go's goroutines. It's safe, embedded in type system (Send etc), has tons of standard tools (Arc, Mutex, mspci channel etc...) that are hard to shoot your foot with.<p>When people talk about Rust's complicated nature, I wish more emphasis is made on how it completely eliminates entire categories of bugs <i>even within a multi-threaded context</i>. As a corrolary, it really makes some parts of programming hard in other languages, nearly trivial in Rust.
Very good article, and these types are essential to have in your Rust "vocabulary".<p>I've seen programmers fight the borrow checker a fight they can't win, because `Arc<Mutex<Object>>` has a non-zero overhead and looks uglier than a plain `Object` or `&Object`. However, if the program has object lifetimes that aren't statically known and/or shared mutable state, these are simply the correct types to use (e.g. event-based systems that can attach listeners have to use these). Rust is just being very explicit about ownership and putting all overheads in your face. In something like Python there's no extra syntax for this, because every object is automatically under a lock and has a refcount.
One option the author didn't mention is that threads can join with a value, so instead of needing scope it could have looked like (on my phone so syntax is probably not quite right):<p><pre><code> let user = todo!();
let handle: JoinHandle<User> = spawn(move || {
// do stuff with user
// hand back user
user
});
// wait for thread to stop and retake ownership of user
let user = handle.join();
</code></pre>
I used this recently to remove locking in a worker thread and it was a big performance boost, <i>and</i> made the code nicer -- win/win.
Every language is hard when you are working with hard problems (e.g. concurrency).<p>I've also found Rust to be hard until I got a decent understanding of the borrow checker and how it works.<p>After that, the only times I found Rust to be hard were when I was trying to make it conform to my way of thinking, rather than changing how I approached the problem to match the way Rust was designed. I've had a similar experience in other complex and well-designed languages such as Clojure, Erlang, and Haskell.<p>In my experience the benefits of Rust (safety-guarantees, speed, good ease of use vs complexity tradeoffs) much outweigh the quirks and learning curve.
A Rust newbie here. Can someone explain why rustc complains that the clojure may outlive the function ? I mean we are joining on both thread handles so the main function has to block until they finish right ? Shouldn't RAII get rid of the clojure objects ?
I think a programmer can get over the "Rust is hard" part after writing certain amount of code. The type system and the borrow checker will just become intuitive enough for a programmer to grasp. I do have a question about productivity, though: what added productivity does Rust bring over languages like Go or Java for writing RPC/HTTP services, given that Rust requires an engineer to think about memory management all the time, while GC languages don't?
I really liked this article, but if I can provide some sort of drive-by advice (also for others looking to write technical content), providing some examples of where to <i>use</i> various traits would really help, e.g. what kind of data structure one would implement !Send on.
Theres a lot of criticism here about “async rust”. I find this wording strange, I use rust asynchronously with rtic (realtime interrupt concurrency) for low level work. Its really excellent. Are peoples criticisms specifically about inline async?