That hasn’t been my experience. Rust (the language) doesn’t seem to get any more complex as programs get bigger. Lifetimes, while complex in isolation, tend to compose really well.
Most of the pain of learning rust seems to be experienced up front. (Well, other than async but I don’t consider that ready yet).
In comparison, my experience of C++ was that it has way more “spooky action at a distance”. A bug in one part of the code will cause problems in another totally unrelated part of the code. I’ve had memory bugs in C++ which took weeks to track down. Maybe C++ has gotten better - I haven’t touched it in over a decade. I haven’t wanted to. And I can’t see many reasons I’d pick it up now that I know rust.
Not sure how limiting the discussion of a language to just the features included in the 3rd standard and forward makes sense. Particularly when the old stuff is still present and valid in the later standards.
Just because you want to use some convention curtain off some area of the language doesn't mean it's not there.
This came 2 years after C++11 was finalized, which introduced RAII memory management, threads, range loops and much more, and is the basis for modern C++.
Of course, there are pros and cons to keeping backwards compatibility with old code. Personally I think it's an amazing technical achievement that the same code written in 1987 still works. Particularly for numerical work there are a lot of libraries that would be a massive pain to rewrite correctly, just getting them off of Fortran was an achievement.
In terms of new and old standards coexisting in the same code, of course it isn't preferable, but it is possible which can enable many use cases, eg. in place upgrades. Forcing rewite-the-world is what caused the Python 2 --> 3 migration to be such a mess.
And if you really don't want old features, there are linter rules and compiler warnings which do a great job for this.
Look into rust's editions. Short version: any compilation unit[1] can declare which edition it is written for. The code in that unit must be valid under the rules of the edition, but different units with different editions can be compiled into a larger program.
https://doc.rust-lang.org/edition-guide/editions/index.html
[1] the compilation unit in rust is a crate. That doesn't mean it has to be put into crates.io, just that it has to be cordoned with its own Cargo.toml and any non-public structs/functions/etc will not be accessible from outside the crate.
With the new GCC Rust work I believe a new solution will need to be found, and it will end up more similar to the situation with C++.
Surely you can describe this with more than a throwaway sentence, given that more and more people are seeming to experience the opposite.
>Like JavaScript, yet another language written for bad to average developers to keep them from shooting themselves in the foot.
Nobody would describe JS this way - the entire existence of that language is filled with projects attempting to make it better for "bad to average developers" because it is certainly not what you're describing.
Edit: minor formatting of quotes.
It keeps you from compiling (many of) the bugs you'll happily write and deploy in C++. I don't think there's really much practical difference in "cognitive load" between modern C++ (which is painfully complex in ways that are largely not even useful) and rust. C++ just lets you pretend it's lower and you ship more bugs.
Imo, writing rust is like the best parts of writing C++ with a stern but helpful assistant.
Anyways, unsafe exists so that if rust is genuinely in your way you can still do what you need to do.
Other than the fact that rust can rely on much much stricter aliasing rules and do a bit better on some optimizations because of it.
Usually when people talk about rust getting in their way they mean the borrow checker, which you can ask to get out of your way and it will still prevent bugs around the unsafe code. Bugs that "advanced programmers" are also prone to, especially around concurrency.
The idea that some programmers are so good they don't make simple but consequential mistakes in code that deals in concurrency and memory management is absolutely elitism.
There is no programmer on the planet who can't benefit from the borrow checker, and if there are any who will benefit less than they are "hindered" by it, there are almost certainly vanishingly few.
... But it can't shed the old stuff without breaking backwards compatibility, and that's what bites you. The fact that smart pointers exist now doesn't stop a developer from passing around non -const char* with no size specifier and calling that a "buffer," and because the language is so old and accreted most of its safety features later, the shortest way to express an idea tends to be the likeliest way to be subtly wrong.
This is really just a problem that other languages don't have because they didn't have the same starting point.
If your developers are coming to the table with some C++ tutorial books written a decade ago, good luck. Invest in a decent linter and opinionated format checker.
And so what if Rust is lowering the bar for entry to systems programming? I'd much rather fresh ideas and fresh blood enter the field, than it slowly dying as the only people with arcane C/C++ knowledge slowly retire/die.
Unless you meant actually all of Rust. In that case, please share what's inexpressible in Rust.
At the most basic level, in Rust you cannot overload operators. You have no opportunity at all to code a move constructor. I could list off others all day long, but you probably would not understand most.
Then there are the things the borrow checker will not let you do, that would be correct, but it can't see that. You might say you can put those in "unsafe", but you can't really field a library where users sometimes must put a call in unsafe.
It is easy to insist you have never needed any of that stuff for your library, but that is really because you have constrained what you even think of trying to do by what you know you can do. We box ourselves in this way automatically, and it takes great effort to break out of such a mental box.
I've heard this claim multiple places and I don't really understand it. Operators have corresponding traits that you can pretty easily define for your types.
SQL builder programmers, for example, wanted assignment operator overload.
However, I'd argue that it's the wrong kind of overload to enable. The more code can do behind the scenes, the harder it is to reason about it, e.g. :
c = b;
Is this an assignment? Will it start the DB connection? In Rust, it can be just one thing. By sticking that code in proc macro and translating code, you signal your intent that something funny is happening here and that you should consult docs for more info: sql!(a = b)
> It is easy to insist you have never needed any of that stuff for your library,I didn't say it was easy. I didn't say it was impossible either https://mcyoung.xyz/2021/04/26/move-ctors/.
> Then there are the things the borrow checker will not let you do, that would be correct, but it can't see that.
Sure, but that's the Rice theorem at work (https://en.wikipedia.org/wiki/Rice%27s_theorem). Any non-trivial property of code is undecidable. That's why you have the unsafe escape hatch where you reason about why it's safe.
[1] which isn't that different C++ which prohibits some operator overload, but in C++ the list of operator not overloaded is small
I gave you a working example of operator overloading in Rust a while ago.
Why do you still state that Rust doesn't allow that? Is there a problem with the example?
I know a lot of different languages and have a feature matrix for reviewing them, and I would know if operator overloading didn't work since it's a row in there. It definitely does work in Rust (it's similar to Python's operator overloading).
As someone who isn’t a rust native but an interested outsider, it can obviously be cumbersome to use on my pet projects compared to something like python, js, c# or C. Dealing with references to generically types traits adds a lot of syntactical burden (re: shit for me to type) and defining types and their implementations leaves something to be desired regarding its grammars.
That being said, my toy programs do not require particularly complex types and the rust compiler is nothing short of a brilliant. The book is a surprisingly easy read, the module system is fine, cargo is decent out of the box, and there is an interesting mix of paradigms in the language itself. In my mind, the power of the compiler is certainly the big feature of rust and that compilers input language is decent enough such that I wouldn’t dislike using it as a daily driver.
Also the truly tricky things in Rust are relatively few and can be escaped with an unsafe.
I can't imagine anyone ever describing vanilla JavaScript this way.
It really draws into question the claim that “it's easier to write super complex stuff in C++ than in Rust” when so clearly incorrect about JS. Especially when we have _decades_ of evidence from world-stopping vulnerabilities in the C/C++ ecosystem.
As someone who was writing both in the 2000s: PHP fits this "nicely" haha