4 ms·
> I like the concepts proposed by Rust but do not like fighting with the borrow checker or sprinkling code with box, ref, cell, rc, refcell, etc. I'm not sure
by timschmidt 9mo ago
> I like the concepts proposed by Rust but do not like fighting with the borrow checker or sprinkling code with box, ref, cell, rc, refcell, etc.
I'm not sure why this would be confusing or disliked by a C++ dev.
Rust's Box<T> is similar to C++'s std::unique_ptr<T>.
Rust's Rc<T>, Arc<T>, and Rc<RefCell<T>> serve similar uses to C++'s std::shared_ptr<T>.
Rust's Weak<T> is similar to C++'s std::weak_ptr<T>.
Verbosity of both is nearly identical. The big difference is that Rust enforces the rules around aliasing and mutability at compile time, whereas with C++ I get to find out I've made a mistake when my running code crashes.
- fooker 9mo agoReminds me of “A monad is a monoid in the category of endofunctors, what's the problem?” As you write this, do you not start to see why this would be confusing? Yes, C++ is pretty bad at this too. The fact that these exist and the programmer has to always be consciously be aware of it is an indication that something has gone wrong in the language design. Imagine if you were to write C code in 1970, but you always had to keep track of which registers each variable corresponded to. That is how I look at these. (There were, indeed, early 'high level' languages that required you to do this :)
- timschmidt 9mo ago> The facts that these exist and the programmer has to always be consciously be aware of it This is what separates a systems programming language suitable for OS and embedded development from managed languages, which are not. The complexity ultimately stems from unavoidable details of the hardware. Languages which do not offer similar representations will be incapable of making full use of the underlying hardware, including writing certain projects like bootloaders, firmwares, OSes, etc. Rust is pretty close to state-of-the-art in terms of providing reasonable abstractions over the hardware. It sounds to me like you're used to managed languages with a runtime which are great for certain applications, but unable to be specific enough about memory layout, how data is formatted in memory, etc. for some tasks. Those choices were made for you by the language runtime's authors and necessarily limit the language's applicability to some problems. Rust, C++, and other systems programming languages don't have such limitations, but require you to understand more of the complexity of what the system is actually doing. Any language which provides adequate representations for taking full advantage of the hardware is going to be on a similar order of complexity as Rust, C++, or other systems programming languages, because the hardware is complex. Managed languages can be nice for introducing folks to programming, precisely because much of the complexity is hidden in the runtime, but that can be a double edged sword when it comes time to approach a systems level task. Instead of wishing the language didn't offer those representations, it may be more productive to ask why C++ and Rust converged on such similar ones. Exploration of that question will be enlightening.
- jacquesm 9mo agoThere should be no such difference. The bigger problem is that OS's enforce this duality when in fact there should only be application level software and an absolutely tiny core to handle IPC and scheduling. This then allows you to enforce the boundaries between various bits far more strictly.
- timschmidt 9mo agoIt seems like you think that some shadowy cabal somewhere decided to differentiate systems languages from managed languages and keep them divided. That is not the case. The distinction describes how the language has been implemented, which is based on the choices of the language authors alone, and is usually down to practical considerations about how to implement the thing at all. Saying "There should be no such difference." is a bit like saying bicycles should be allowed on the highway and semi trucks should be accepted on walking paths. The difference is inherent in the thing. A result of how they were built. And what they can and can't accomplish as a result.
- jacquesm 9mo ago> It seems like you think that some shadowy cabal somewhere decided to differentiate systems languages from managed languages and keep them divided. That is not the case. You could have made that point without the strawman, and what a ridiculous thing to say anyway. > The distinction describes how the language has been implemented, which is based on the choices of the language authors alone, and is usually down to practical considerations about how to implement the thing at all. That is so obvious I do not understand what point you are trying to make here. > Saying "There should be no such difference." is a bit like saying bicycles should be allowed on the highway and semi trucks should be accepted on walking paths. The difference is inherent in the thing. A result of how they were built. And what they can and can't accomplish as a result. No, the error is yours: you are interpreting my sentence in a way that is blatantly wrong and then argue with the outcome. I'm not saying that there shouldn't be 'trucks or bicycles' in terms of programming languages. What I'm saying is that the boundary between where you use a 'systems programming language' and where you use an 'application programming language' is artificial and that we are using too much of the former in a place where we probably should be using the latter.
- tialaramex 9mo agostd::unique_ptr<T> is almost exactly Option<Box<T>> The Option is important, Rust's Box<T> is always a boxed T, but std::unique_ptr<T> might not be a boxed T, it might be "disengaged" and there isn't a T C++ move operations are thus closest to Rust's core::mem::take function, they not only move something, they also need to always replace it with some empty default state, in Rust's case specifically Default::default. Box<T> may not implement Default, but Option does so unconditionally, because its default is always just None. You may find when converting some code that you didn't want Option<Box<T>> but only Box<T> because in fact you always have a boxed T here - it's never disengaged, and if you do that then Rust's type system has helped in a small way to clarify your code so that's nice.