3 ms·
> I don't think this is really unique to Rust. Any language that requires you to write stuff down about interfaces might require you to change them in a lot of
by sfink 2y ago
> I don't think this is really unique to Rust. Any language that requires you to write stuff down about interfaces might require you to change them in a lot of places if you get it wrong. E.g. if you get the type of a parameter that is passed everywhere wrong.
My experience doesn't match this. I think the difference is that Rust has... "specific types", to pick an arbitrary term. The types store more information, which means that there are many more ways that you might need to update an interface.
An interface with a function that takes a C++ pointer doesn't imply anything other than that the pointer is valid at the beginning of the calthe return value of l to that function. It doesn't even tell you whether it can be nullptr or not. It might be a pointer extracted from a `std::unique_ptr`, in which case the actual expectation is that the pointer be valid when the function returns. Or it might be passed the return value of `new`, in which case the expectation is that the pointer be either valid but now owned by something else, or invalid when the function returns. And you might change from one expectation to the other merely by removing a `delete` call 7 levels deep, without needing to adjust any of the intervening layers.
Rust, on the other hand, encodes a specific subset of the possible lifetimes that the C++ version accepts, and every intervening layer has to agree on that lifetime or at least the structure of it.
And it's not just lifetimes. In Rust, you'd typically make everything a specific type -- maybe an enum or Option or whatever. In C++, I often find myself intentionally degenerating even (C++) enums to ints when I need to store or output or manipulate them -- I want to test `val < FirstCustomValue` or something. A parameter that started out as an enum with 3 variants can add on a couple of orthogonal bits without perturbing much of anything.
The more specific the types used in practice, the more they'll need to be adjusted to accommodate changes. C++ doesn't even have the facilities for specializing the types as precisely, but more importantly types are typically left pretty loose in practice -- at great cost to stability and correctness, but with resulting benefit to adaptability.
A lump of mud is much more adaptable than a carved sculpture.
- IshKebab 2y agoIt sounds like you're agreeing with my point to be honest. The problem isn't Rust or the borrow checker; it's simply checking lots of things on interfaces. The more you check, the more you'll have to change when you get it wrong. Rust happens to check quite a lot. I imagine it is similar for things like monads in Haskell, or probably formal languages like Lean and Dafny... but I have no experience of that so it's just a guess.
- sfink 2y agoNo, I'm not agreeing with you. You're agreeing with me. Wait a minute... :-) Sorry, somehow I managed to quote the portion of your message that I was agreeing with. You just said it more concisely than I could. The aspect I disagree with is whether brittleness to change is more due to the complexity of the borrow checker vs interfaces with very constrained types. I mean, the complexity of the borrow checker definitely factors into it, especially with how late it runs (as you said) and the fact that it's all or nothing, which makes it hard to change things incrementally. But (imho) the borrow checker is less complex than, say, the rules around C++ constructor variants. And RVO/NRVO. And name lookup. And definitely less complex than undefined behavior. I'd rather memorize the borrow checker than those. They contribute to some amount of brittleness to change, especially when monkeying with move constructors, but in practice it seems far less than Rust. I really think it's more about the specificity of types in the language. I should probably mention that I still think it's a good tradeoff for many of the types of programs I write, but it is a tradeoff. Anyway, this is all more just a realization that you sparked in me. It's ok if we, uh, disagree to agree.