4 ms·
> Rust does have a lot of complicated stuff, but almost all of it secretly turns up if you wanted to be good at C++ too. This is mostly true. As FP and Rust ha
by verdagon 5y ago
> Rust does have a lot of complicated stuff, but almost all of it secretly turns up if you wanted to be good at C++ too.
This is mostly true. As FP and Rust have shown us, if you can treat an input data set as immutable, while building up the result data, you have a much easier time. I bring those patterns into my C++, which speaks to your point.
I'd offer one exception though: mutability xor aliasability on a per-object basis is something I wouldn't take to my C++ code. It may be the core of Rust, and it's a neat tradeoff that enables some of its other benefits, but the indirect complexity cost is too high, IME.
> Oh there is just no way it's harder to learn than C++.
I think the jury's still out on this one.
C++ has complexity, but has the benefit of a gradual learning curve. You can start with C, slowly add `virtual`, then add templates, then add the STL.
Rust has just as much complexity, and forces it all on you at once. Because of that, it is harder to learn.
Some people say Rust's rules are intuitive. I have to disagree. These years of working with Rust and teaching Rust to others have made it clear to me: though the basic concepts are simple, the architectural implications and workarounds are not.
I'm not saying C++ or Rust is better. But C++ is slightly easier to learn, IMO.
I commonly hear "But it's hard to learn how to use C++ safely!" and I generally agree with that. ASan has made things much easier in that regard, but C++ will probably never catch up enough for some use cases.
- zozbot234 5y ago> I'd offer one exception though: mutability xor aliasability on a per-object basis is something I wouldn't take to my C++ code. Rust has "interior" mutability for when you need mutable access to shared data. It works very similar to the "mutable" keyword in C++ except that it's always type-driven, as opposed to something being specified as part of a declaration.
- verdagon 5y agoAgreed! While it's not considered "idiomatic" Rust (from all my conversations on the Rust discords), I think that interior mutability is a totally fine thing to reach for in certain cases, at the upper levels of one's architecture. But then, once your code has RefCell<> everywhere, you're incurring runtime overhead, at which point one might as well switch to a language that makes those tradeoffs easier to wield. This'll get even better in the near future; a lot of languages are improving in this regard (Cone, Lobster, etc).
- zozbot234 5y ago> But then, once your code has RefCell<> everywhere, you're incurring runtime overhead The runtime overhead is quite trivial (a single word per object IIRC, which is accessed w/ simple increments/decrements/checks as needed) and work is ongoing on abstractions that don't incur any hidden overhead (called 'GhostCell').
- verdagon 5y agoThe runtime overhead of RefCell<> is usually accompanied by some other runtime overhead. To be reachable from multiple places, it usually needs to be stored in some relatively central location. If it's a rather short-lived object and we don't need to reuse its location, it can be in a Vec, which involves bounds checking and O(logN) calls to malloc, which is not amortized. Sometimes we can put short-lived objects in an arena, which is the best option, but they are very memory hungry, which has its own costs. If it's longer lived, we can use a Vec with indices or a type-pool, but we risk use-after-"release", which can be a privacy risk and defeats some of the nice "sanity" properties of Rust code (this is still a good option in some cases, IMO). If it's longer lived, and we don't want those drawbacks, we have to fall back on something like Rc or generational indices, which both have their runtime costs. IME, only a very specific kind of use case can avoid any of this runtime overhead. When you get to the more complex use cases, especially with lots of unavoidable state, these overheads appear more and more, and make the whole situation a little less clear-cut. (This was a rather hand-wavy explanation, I can make it more accurate if you'd like)
- vvanders 5y ago> C++ has complexity, but has the benefit of a gradual learning curve. You can start with C, slowly add `virtual`, then add templates, then add the STL. Having seen teams go Java -> C++ and other teams go C -> C++ I don't really think that's the case. The former leans on shared_ptr everywhere, the latter ends up hitting footguns with implicit behavior around move semantics, RAII(seen more than a few use after free here) and the like. ASAN and other tools help, but assume they are run regularly and kept to a level of rigor I haven't always seen in codebases.
- moldavi 5y agoTo be fair, people coming from other languages lean heavily on Rc/RefCell too, and sometimes (uh oh) unsafe blocks. In both cases, one benefits from input from those experienced in the language. (not saying c/c++ is better than rust, just commenting on the difficulty)
- vvanders 5y agoYeah, but rightly so those are "escape hatches" because you can leak memory with Rc/shared_ptr. With C++ unless you have someone experienced on a team there's a host of "unknown unknowns" that feel like the team is making progress but then having to pay the cost when it blows up and usually when schedule pressure is near the highest point. Same for the build systems, retrofitting LTO is not a fun experience. Rust in contrast calls out many of those things upfront, I've found those guardrails prompt conversations in tradeoffs and conscious choices(to say use Rc/RefCell) you'd be making anyway in C++.
- moldavi 5y agoSo it's okay if rust does shared ownership, but not okay for c++? I'm not attacking rust, btw. We all know c/c++ isn't great. Theres plenty of aspects where rust is better, and plenty where c++ is better. But we're just talking about difficulty, and in this context it's fair to say rust isn't necessarily better than c/c++.
- 5y ago