In my experience, it mostly does. I’m now significantly more productive in rust than C, and I feel much more pleased with the end result.
I still find it takes a lot more effort to write rust than javascript though. Both more thinking per line, and it often takes more lines of code. The resulting software is faster and more correct, but it’s not a uniform win. I still reach for javascript for “code as content” - like UI code.
Rust’s async story is awful. Pin is confusing. Async doesn’t play nice with other rust features (like traits). There’s no async streams and it’s extremely difficult to code your own. Solutions to these problems (like GAT and TAIT) have been proposed, coded and discussed for 6 years or something but they still haven’t shipped. I’m quite frustrated with how slowly the language is moving to fix obvious problems. And it seems to be getting slower as more people try to “help” (by chiming in on GitHub).
But I really like rust-sans-async as a language for infrastructure code. The stuff I’ve built with it is bonkers fast, safe and correct. The crates ecosystem is fantastic. (Much higher quality than npm). And the community is smart and lovely. It’s not the most productive language but it fits the “better C” niche really well.
Side note, Rust best practice seems to be in favor of getters and setters like Java and several popular libraries I've seen don't expose struct fields directly instead opting for set_x() and x() methods. Give it a few years and I'm sure Rust will have its own Lombok crate generating getters, setters, and constructors too.
I don’t love rust. I think rust has some fair critiques to be made of it.
It’s not, and never has, or (probably) will be the answer to all problems.
Don’t use it just because it’s popular; why are you trying to use it, and what are you using instead?
I’ll eat my hat if you can convince me that rust is more of a pain in the ass than c++. I think cpp is a stupid broken ecosystem, and the fact that rust went all in with a single unified package manager makes the comparison a non-event.
So… compare apples to apples right?
“pre-alpha” language? I don’t even know what you mean by this; but, it’s ok not to love it.
There are things I dislike about it too.
It is verbose.
I still use it though; it’s better than the alternatives for what I’m doing.
At this point, I kind of feel like, if you're writing safe C or C++, being mindful of where the data goes and why, you're pretty much writing Rust that compiles.
Exactly. If you're using modern c++ and you actually know what's undefined behavior and what's not, you're doing rust. The only difference is c++ compilers don't error out on the undefined behavior. Actually it wouldn't be that hard to write a c++ compiler that errored out in this way. unfortunately, it'd break all c++ programs today.
I have heard all the arguments for using Rust in GUI apps, but realistically they seem to be very weak to convince a serious team of developers to choose between the alternatives.
There's definitely a learning curve (I think everyone agrees with that one), which might be what you're feeling now, but that quickly goes away once you pick up some speed. I would say keep on learning Rust and the language will grow on you.
But if you avoid trying to be really annoying with the type system like the majority of the ecosystem is, and slap Arc/RefCell/heap allocations everywhere, the language turns back into a high-level language again.
Unfortunately, stepping outside the realm of ``core`` and ``alloc`` and ``std`` means having to repeatedly step on overly clever landmines everywhere you go.
If you find it easy to build a linked list or graph in C, you can do it just as easily in Rust — use unsafe, and you have your easy linked list, with exactly as much safety as it had in C. Sure, it’s more challenging to build a fully memory and thread safe linked list or graph, but it’s actually hard as hell to do that in C too. Other languages make it easy to build one with these guarantees only by requiring significant runtime support, which is out of scope for Rust.
In the end, it’s pretty unrealistic to expect that any language would allow you to write a guaranteed memory and threadsafe graph structure with zero runtime overhead, without a lot of knowledge, time, and attention on your part — there are no silver bullets.
And if you’re using Rust for anything real you’re generally not doing sophomore computer science homework like this anyway.
In practice, I find that unsound libraries frequently get written and used unknowingly in the wild. I've commented on this earlier at https://news.ycombinator.com/item?id=31897503.
In short, I believe that Stacked Borrows places unreasonable and unattainable requirements on authors of unsafe structures and algorithms, which serve as the foundation for practically all safe code (outside of the vanishingly rare case of code operating on tree-shaped fixed-size variables allocated solely on the stack, and never creating aliased mutable pointers).
The rest of what your wrote is completely irrelevant to the original point: this seems hard in safe Rust only because you’re comparing it to doing something totally different and simpler in C.
Grind your axe about stacked borrows elsewhere.
You said Rust linked lists have "exactly as much safety as it had in C". Are you seriously arguing that C linked lists are just as wrong as Rust ones, by saying a CS student is as likely to write an incorrect C linked list as a hardened professional is to write an incorrect Rust linked list (eg. Tokio and https://gist.github.com/Darksonn/1567538f56af1a8038ecc3c664a...)? Stacked Borrows ensures that translating sound C code into idiomatic Rust APIs produces needlessly unsound Rust code, and the Rust language (or a specification if it existed) means C translated directly into raw-pointer Rust is unidiomatic and you're fighting the language every step of the way (no autoderef, no -> operator). At this point, an experienced programmer is more likely to write and use a correct C linked list than write and use a Rust one.
What?
No, I’m saying that writing a linked list in C is “easy” if and only if your implementation doesn’t even bother to try to cope with the 9000 foot guns C offers you — that your easy C graph data structure is basically always a disaster of Undefined Behavior and thread unsafety, because if you try to make it otherwise, it will cease being at all easy. It will become in fact really fucking hard
So when I say “you can have your easy C-style linked list in Rust, just use unsafe”, I agree entirely: the Rust implementation will also likely be a gigantic clusterfuck of Undefined Behavior. That’s the entire point: it’s only ever easy in either language if you’re willing to blow both of your feet and you dick clean off. It’s easy only if you’re so inexperienced and naive that you don’t even perceive the dangers of the highly efficient dick-and-leg removal device you’ve built in C, and whine on forums about how mean-old-Rust is hard in comparison because it keeps refusing to compile your dick_exterminator.rs file.
That’s the Apples to Apples comparison. Which unsafe thing is harder to get right, I don’t honestly give a flying fuck about. Now, it’s highly de-fucking-batable that it’s easier for “an expert C programmer” to avoid undefined behavior entirely in an arbitrary mutable graph implementation in the presence of multithreading unless we’re talking about an entirely mythical level of expert here, but that’s utterly offtopic to the discussion at hand. You were just looking to grind a fucking axe about Stacked Borrows and decided to rant at me about it, but it really has fuck all to do with anything I was saying, man.
You can have an easy graph structure in Rust in the only way you can easily have one in C: by not giving a single shit about correctness.
And C is not a dick-and-leg removal device, it's a direct representation of runtime semantics (aside from signed integer overflow which is avoidable, type-based alias analysis which is rare, etc.), and any sound Rust code which doesn't transmute types can be compiled into equally UB-free C code, and even Rust which commits UB by violating SB (many unsafe libraries) can be transpiled into UB-free C code as long as you don't use `restrict` when inappropriate. Rust is merely a possible way to organize a program to avoid UB, to be followed when helpful (RAII, catching use-after-free in application logic, avoiding reference counting errors, multithreading) and replaced when it impedes writing low-level code. It's not a religion where apostasy is punished by castration.
I'm criticizing Stacked Borrows because I've seen more than enough evidence that it's an unreasonably stringent memory model for writing unsafe code. Please stop putting words in my mouth and misrepresenting my positions as profanity-laced straw men, like "not giving a single shit about correctness".
lmao. profound stuff man.
> It's not a religion where apostasy is punished by castration.
What on earth are you even talking about. It was just a metaphor for runtime crashes you absolute dingus.
> I'm criticizing Stacked Borrows because I've seen more than enough evidence that it's an unreasonably stringent memory model for writing unsafe code
I didn’t ask! I don’t care! At no point in my life have I cared about anything less than I care about what “nyanpasu64” thinks about Stacked Borrows. Take the hint you tedious dork.
If my project requires the memory safety that rust offers, I’ll choose rust. But most of the time I’ll pick something else to lower my mental load when coding.
On the other end of the spectrum I would say Go is, with its lack of "advanced" or functional language features and sans-syntactic-sugar straight forward approach. I always feel like I have oncoming RSI when I write Go, its just so verbose and un-dense and frankly boring. No room for (too much) cleverness.
At the same time I would guess real development teams using Go are more productive (in problem spaces where Go can be used instead of Rust of course). Especially if you factor in mentoring of junior colleges new to the language etc.
That is mostly only true for very early beginners.
There are certain patterns you have to learn and understand, especially for developers not accustomed to thinking about lifetimes ( which applies to most developers that only have experience with GC languages).
And sometimes you do have to battle the compiler, even with experience.
But most of that goes away pretty quickly once the language clicks for you.
After that Rust can still feel restrictive, but that's because there are very few languages that enforce as much correctness at compile time.
That very well can mean that Rust just isn't a good fit for certain domains - which is perfectly fine!
Can you give any concrete examples of things that give you this impression?
* Rust has no way to talk about heap allocations succinctly other than Box; an actual type I had Option<Box<[Box<[&'a str]>]>>. It's more than just Box and Option being poor abstractions for the heap and nullability respectively, but the fact that Rust is a systems programming language and provides nothing to actually help with even mundane problems that arise in systems programming
* there has been almost no iteration in the design space of lifetimes despite being a cornerstone feature of the language
* prolific do_x and do_x_mut methods; there has to be a better way than countless *_mut methods for a language where mutability is so important
My general impression of Rust is that it ships a MVP version of a feature and never really tries to iterate on it, or iteration happens incredibly slowly (const generics being the only notable exception I can think of where almost every release seems to have something to say about const generics). And I get it, things like GATs are important for the language long term, but the "ivory tower" approach has left the rest of the language feeling neglected IMO.