7 ms·
This is a different issue. The problem that the author is observing is that Rust operates on the hypothesis that the ownership relation is mostly left-unique an
by rbehrends 10y ago
This is a different issue. The problem that the author is observing is that Rust operates on the hypothesis that the ownership relation is mostly left-unique and acyclic and that you run into problems when this hypothesis doesn't hold. And this affects not only explicit data structures, but also the implicit structures that involve stack frames (local variables, closures, etc.).
While Rust has mechanisms to deal with this (copying, Rc<T>, etc.), all these mechanisms add pain points, and for problems that are not just theoretical. It affects a number of design patterns, closures that survive the scope they were created in, functional-style programming, functional data structures, any data structure that naturally involves a DAG or cycles.
The difference compared to a (good) static type system is that a good [1] static type system does not measurably reduce expressiveness; Rust's ownership model does.
This is not to say that there isn't a point to Rust's model. Rust directly competes with garbage collection as the main alternative model to achieve memory safety and is an obvious choice in cases where garbage collection is not a realistic option. But where garbage collection is an option, the tradeoffs that Rust makes become much less attractive.
[1] Obviously, primitive static type systems (example: Java up to version 1.4) do pose a problem.
- humanrebar 10y agoFirst, the expressiveness is all there. You just need to explicitly say you are responsible by using unsafe blocks. So risky pointer and allocation logic becomes the programmer's job, not the borrow checker. Second, this article only considers the costs of a stricter borrow checker, not the benefits. It will be more work for the coder to have to think about how allocation and ownership is communicates. But I've been through much bigger headaches in production code at inconvenient times (for the business plan) due to dangling pointers, multi-writer concurrency bugs, and ill-defined memory models in software designs. Even if Rust is much harder than alternatives instead of just different, and even if that's inherent in borrow checking, it's not clear that it's still not worth it in the long run.
- jackmott 10y agoIt might be worth it over C++, but assuming the task at hand is not hindered by garbage collection, is it ever worth it over an ML style language? It certainly takes a lot more typing to get things done.
- pmoriarty 10y agoI think it's always worth it to learn new paradigms. They expand your view of what's possible, and give you a richer understanding of the other languages you already know, understanding some of the tradeoffs they made, and give you other conceptual and practical tools in your toolbox. It's much like visiting other, radically different countries than the ones you've been brought up in. Even if you don't wind up moving there permanently, you'll be richer for the experience.
- Bartweiss 10y ago> Even if Rust is much harder than alternatives instead of just different, and even if that's inherent in borrow checking, it's not clear that it's still not worth it in the long run. One obvious argument is that Rust frontloads its difficulty. It's a terrible tool for most 30 line tasks, simply because the majority of your work will go into arguing with the compiler. But that's true of a great many tools - if there's an adequate payoff in safety and comprehensibility at scale, they can still be worthwhile. That doesn't solve the learning-and-usage problem, though. Most of us are aware that the explosion of dangerous-at-scale tools like Javascript is largely because no one adopts a language that's unfriendly until you reach enterprise sizes. Even if Rust is "worth it", it's unlikely to catch on while the learning experience feels like pulling teeth.
- bluejekyll 10y ago> It's a terrible tool for most 30 line tasks, simply because the majority of your work will go into arguing with the compiler. This arguing with the compiler is really only while you are learning Rust and it's nuances. For me the first two weeks were this way, then I started thinking more in Rust terms. Now I rarely deal with the borrow checker at all, but I do end up in some complex type situations. You're spot on with the frontloads difficulty. Honestly though, I can't think of any language that I've learned that in under a few weeks I knew how to properly do things in the language. Python was this way for me. My code looked like C when I started with it, and then I learned after a few weeks about 'with' and 'yield' and started writing real code. Rust is worth the initial investment, but the first two weeks will require some perseverance.
- spullara 10y agoI think the difference is that while you are coding Python in a C style the code is working. The front loaded nature of Rust means that you are in a constant fight to get something to run.
- bluejekyll 10y agoYes, and I understand how frustrating it can be, I had to learn it, too. My only point is that after you spend the time with it, the cognitive load becomes a lot less and you've learned some new things about programming at the same time.
- rbehrends 10y ago> First, the expressiveness is all there. You just need to explicitly say you are responsible by using unsafe blocks. So risky pointer and allocation logic becomes the programmer's job, not the borrow checker. No, unsafe would be overkill and if you needed unsafe, it would put Rust at a massive disadvantage vis-à-vis garbage-collected languages. Simply put, Rust doesn't handle multiple ownership well. It results in syntactic bloat and/or runtime overhead. But multiple ownership occurs naturally in a number of real-world programs. > Second, this article only considers the costs of a stricter borrow checker, not the benefits. This is why I very specifically mentioned that it's a tradeoff.
- bluejekyll 10y agoI think you're implication here is that other languages do handle multiple ownership well. What I think you find in Rust, is that the guarantees you need to make when using unsafe in these limited situations, are the exact same guarantees you need to make in a language like C or C++. Destroying a circular list takes some thought to make sure you don't double free, same as Rust. Rust just makes those sections of code very explicit and calls your attention to it, while in C you may end up with a segfault, or worse a program that only shows odd bugs during runtime. At least Rust is telling you that you need to put some extra thought in this section.
- rbehrends 10y agoYour assumption seems to be that I'm talking about languages with manual memory management. I'm not; I'm talking about garbage-collected languages, where you get memory safety automatically, regardless of ownership rules. In fact, C++ has some of the same problems that Rust has when it comes to multiple ownership.
- kaoD 10y agoThen use https://github.com/Manishearth/rust-gc https://github.com/Manishearth/rust-gc if you're willing to pay the price of a GC (still experimental). Or better, stick to a GC'ed language. If you don't need manual memory management, it's obviously going to be a burden. There are still use cases for manual memory management though, and that's where Rust comes in. Use the right tool for the job.
- rntz 10y ago> The difference compared to a (good) static type system is that a good [1] static type system does not measurably reduce expressiveness This is pseudo-jargon. What counts as a "measurable" reduction? Do you have any substantive evidence that "good" typesystems don't reduce it? And why are only type systems which satisfy this property "good"? You talk cogently about tradeoffs later on, but this sentence taken literally suggests only a type system which doesn't make this particular tradeoff can be "good". Why? My go-to languages for the past few years have been Haskell and Racket. There have definitely been times I picked Racket because I knew Haskell's type system would interfere with my expressiveness. Certainly Haskell is less restrictive than Rust with regards to ownership, but all type systems restrict you. I think GP is spot-on in pointing out that you just get used to it over time as you learn to think and code in ways that avoid pushing against the type-system's weak spots. > But where garbage collection is an option, the tradeoffs that Rust makes become much less attractive. Yes, precisely. It's not a fundamentally different issue from getting used to other static type-systems; it's just a different tradeoff.
- rbehrends 10y ago> This is pseudo-jargon. How do you measure expressiveness? Actually, not jargon. I had Matthias Felleisen's characterization of expressiveness [1] in mind (incidentally, he's also one of Racket's authors). > Do you have any substantive evidence that "good" typesystems don't reduce it? If we want to be precise, there is a continuum from statically to dynamically typed language. A dynamically typed language is, after all, the same as a static language with just a single polymorphic type. This means that we can trivially translate a dynamically typed program into a statically typed program, though obviously we don't gain anything by that at this point (this is essentially an argument that Bob Harper has advanced before) and we pay for it in additional verbosity. However, in practice we know that we don't need all that flexibility and can constrain types more, allowing us to get better type guarantees; static types then also allow us to do things that we can't do in a dynamic language (such as compile-time overloading). [1] http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.51.4656 http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.51.4...
- 10y ago
- braveo 10y agoI agree, ayende is a C# person, he's well aware of statically typed languages. I also agree about your other points, I think maybe one of these days the borrower will become more sophisticated, but these issues he's complaining about are the exact reason I put Rust down. It just felt too sophomoric, as if the language wasn't really ready. Not all is bad, I really like the way errors are handled in Rust, but there are definitely some problems with the approach they take.