Live data from Hacker News

My negative views on Rust (2023)

chrisdone.com

141–150 of 308 posts

Re: My negative views on Rust (2023)

#141

I think to some extent Rust is a victim of its own unreasonable effectiveness. It is great at its narrow niche of memory safe low level programming, but frankly pretty good at lots of other things. But at these other applications some of its design principles get in the way - like the pedantic borrow checker. Languages not used outside their niches don't tend to collect such criticism. Python is a bit like that. It i…

People keep talking about the borrow checker. I have written over 70k lines in Rust so far and it hasn't really been that big of an issue. There are large-ish projects like Zed and Zellij in Rust which seem to be pretty straightforward code as well. I feel it's a bit overblown the whole borrow checker issue.

Re: My negative views on Rust (2023)

#142

Earlier quoted context omitted.

What does "think about your memory layout" mean? Can you provide an example? I've seen this brought up a few times on this thread and have no idea what people are referring to when they say it. As for the rest of your list - I'm not sure why rust is special in regards to "the specific time you grab and release resources" or "inter-thread interactions". Seriously - I have to think about when I acquire and release reso…

Again, the subtext here is GC versus direct control of memory lifecycles, and it is probably not reasonable to argue that there isn't a tradeoff here --- that every application is as gracefully expressible in one as the other, so long as you "git gud" at it. Both sides of this debate are guilty of deploying that trope.

I'm not arguing that there isn't a tradeoff, or about "git gud". I'm literally and genuinely baffled about how one can magically elide knowing if a file is open or closed (or the equivalent) when using a resource. Like I can't think of a single language that doesn't make you explicitly obtain resources, and most of the GC languages do the same thing as rust for casual closing - just let the handle go out of scope.

Even for memory, a huge amount of the rust I write isn't performance code - I don't understand why it's a mental burden to write

let x = vec![a, b, c];

When the equivalent in python is:

x = [a, b, c]

Nothing about either requires a lick of memory allocation thought, nor about memory layout. Sure in rust I have to think about what I'm going to do with that vec in rust and the mutation story up-front, but after enough lines of python I have also learned to think of that up front there too (ortherwise I know I'm going to be chasing down how I ended up mutating a copy of the list rather than the original list I wanted to mutate - usually because someone did list = $list_comprehension somewhere in the call stack before mutating).

I'm not being disingenuous here - I literally don't understand the difference, it feels like an oddly targetted complaint about things that are just what computer languages do. To the best of my ability to determine the biggest differences between the languages aren't about what's simple and complex, but how the problems with the complex things express themselves. I mean it's not like getting a recursion limit error in python on a line that merely does "temp = some_object.foo" is straight-forward to deal with, or the problems with "for _, x := range foo { func() { stuff with x } }" are easy to understand/learn to work with - but I don't see people running around saying you shouldn't learn those languages because there's a bunch of hidden stupid crap to wrap your head around to be effective. (and yes, i did run into both those problems in my first week of using the languages)

In all the languages there are wierd idioms and rules - some of them you get used to and some of them you structure your program around. Sometimes you learn to love it, and sometimes it annoys you to no end. In every case I've ever found it's either learn to work with the language or sign up for a world of pain, but if you choose the former everything gets easier. When a language makes something seem hard, but it seems easy in my favorite language, well, in that case I've discovered the complexity is there in both, but when it's hidden from me it limited my ability to see a vast array of options to explore and shown a whole new set of problem solving tools at my disposal.

I still don't know what people mean when they talk about "having to think about memory layout"... like seriously to me it's: Thinking about pointer alignment and how to cast one struct into another in C... something I've only had to think about once in any language across a fairly wide range of tasks. If this is what's being referred to, I'm baffled about how it's coming up so much, but i suspect this isn't what people mean, and I don't know what they actually do mean.

Re: My negative views on Rust (2023)

#143
post #35
post #11

My big problem with Rust is too much "unsafe" code. Every time I've had to debug a hard problem, it's been in unsafe code in someone else's crate. Or in something that was C underneath. I'm about 50,000 lines of Rust into a metaverse client, and my own code has zero "unsafe". I'm not even calling "mem", or transmuting anything. Yet this has both networking and graphics, and goes fast. I just do not see why people see…

> Rust does need a better way to do backlinks. You can do it with Rc, RefCell, and Weak, but it involves run-time borrow checks that should never fail. Those should be checked at compile time. It's not clear to me how rustc could detect a dangling backlink in a tree structure at compile time. Seems impossible short of adding proofs to the type system.

If the language actually supported a full set of memory policies it would be quite possible.

Unfortunately it only thinks about are unique, an opinionated form of borrowed ownership, and a little bit about shared (weak I think is punted entirely to the library?), and not all other ownership policies can effectively be implemented on top of them.

The usual thing approach would be:

  given two types, P and C (which may be the same type in case of homogeneous trees, but this), with at least the following fields:

  class P:
    child1: ChildPointer[C]
  class C:
    parent: ParentPointer[P]
Then `p.child1 = c` will transparently be transformed into something like:

  p.child1?.parent = null
  c?.parent?.child1 = null # only needed if splice-to-steal is permitted; may need iteration if multiple children
  p.child1 = c
  p.child1?.parent = p
Note that ChildPointer might be come in unique-like or shared-like implementations. ParentPointer[T] is basically Optional[UnopinionatedlyBorrowed[T]].

A have a list of several other ownership policies that people actually want: https://gist.github.com/o11c/dee52f11428b3d70914c4ed5652d43f...

Re: My negative views on Rust (2023)

#144

Earlier quoted context omitted.

I think in general python gets used because of laziness and vitality. It's just the dumb shit that X person learned first because Y person before then was taught it because it was easy even though it's maybe not even the right choice for example, you can't properly write a working webserver in python without {venv, uvicorn, celery etc.} and if youve ever worked in another language its like why the hell is this shit h…

I disagree re Python. It is a brilliant, flexible scripting language. It is easy to build expressive libraries such as pytest or argparse, with deep introspection. It is easy to prototype by subtly changing return types, or even keeping them flexible. It is really easy to eg build a custom data type and build custom expression trees, such as what ML often needs. It has a number of features (often stemming from the ab…

If you feel that way about python, it's really just likely you haven't tried anything else better.

And anyways you probably shouldn't be serving a website with a scripting language (php and perl are great examples of why not). You probably shouldn't be deploying ml with a scripting language (maybe training is fine, if you're not doing distributed training). You probably shouldn't have too many core os components in a scripting language lookin at you Ubuntu, you probably shouldn't write a cloud (openstack) using a scripting language. What happened to "right tool for the right job".

Re: My negative views on Rust (2023)

#145

Earlier quoted context omitted.

Just so we're clear, your reference points for "good for high-level application code" are systems code and game engines? :)

Games themselves, not game engines. Systems code, game engines, and games. This isn't meant to be an exhaustive list--it's just the domains I have experience with that Rust was a good fit for. Lest it seem like I'm saying Rust is a good fit for everything I've done, I also worked on Firefox where the UI was JavaScript, and I wouldn't hurry to rewrite that code in Rust. Nor would I want the throwaway stuff I write in…

I'm just saying, games are exactly one of the things I would assume Rust would be a natural fit for. :)

Re: My negative views on Rust (2023)

#146

"There are only two kinds of languages: the ones people complain about and the ones nobody uses". --- Glad to see fluffy negative articles about Rust shooting up the first slot of HN in 20 minutes. It means Rust has made finally made it mainstream :) --- The points, addressed, I guess? - Rust has panics, and this is bad: ...okay? Nobody is writing panic handling code, it's not a form of error handling - Rust inserts…

> Rust has panics, and this is bad: ...okay? Nobody is writing panic handling code, it's not a form of error handling

As far as I know, the issue with the panics is that things panic a lot. Times when C or C++ will limp along in a degraded state and log something for you to look at will cause your Rust program to crash. That turns things that are not problems into things that are problems.

Re: My negative views on Rust (2023)

#147

Earlier quoted context omitted.

Again, the subtext here is GC versus direct control of memory lifecycles, and it is probably not reasonable to argue that there isn't a tradeoff here --- that every application is as gracefully expressible in one as the other, so long as you "git gud" at it. Both sides of this debate are guilty of deploying that trope.

I'm not arguing that there isn't a tradeoff, or about "git gud". I'm literally and genuinely baffled about how one can magically elide knowing if a file is open or closed (or the equivalent) when using a resource. Like I can't think of a single language that doesn't make you explicitly obtain resources, and most of the GC languages do the same thing as rust for casual closing - just let the handle go out of scope. Ev…

Totally reasonable question. The issue isn't how hard it is to get the memory for the a vector, but rather what you have to do to store references to that vector elsewhere in your code, so that the compiler can prove its bounded lifetime and release resources without creating UAF bugs.

Re: My negative views on Rust (2023)

#149
post #68

Earlier quoted context omitted.

> Does Rc really resolve the core problem this post is talking about, which is that it's really painful to naturally express tree and graph structures in Rust? No, but Gc will not resolve the core problem either. The core problem is that rust forbids two mutable pointers into one chunk of memory. If your tree needs backlinks from child nodes to parents, then you are out of luck.

In what way am I "out of luck"? It's trivial to express a tree, including one with backlinks, in Java.

Java doesn't enforce the rule "mutable XOR shared". But if you have a link "child" in the parent node, and a link "parent" in the child node, then parent.child.parent == parent, and compiler cannot know it.

So Rust as the language makes it impossible to do with &-pointers, while standard library of Rust allows it to do with combination of Option, Rc, RefCell but it is really ugly (people above says it is impossible, but I believe it is just ugly in all ways). Like this:

type NodeRef = Rc>;

struct Node { parent: Option, left: Option, right: Option }

So the real type of `parent` field is Option>>. I hate it when it comes to that. But the ugliness is not the only issue. Now any attempt to access parent or child node will go through 2 runtime checks: Option need to check that there is Some reference or just None, and RefCell needs to check that the invariant mut^shared will not be broken. And all this checks must be handled, so your code will probably have a lot of unwraps or ? which worsens the ugliness problem.

And yeah, with Rc you need to watch for memory leaks. You need to break all cycles before you allow destructors to run.

If I need to write a tree in rust, I'll use raw-pointers and unsafe, and let allergic to unsafe rustaceans say what they like, I just don't care.

Re: My negative views on Rust (2023)

#150
post #68

Earlier quoted context omitted.

> Does Rc really resolve the core problem this post is talking about, which is that it's really painful to naturally express tree and graph structures in Rust? No, but Gc will not resolve the core problem either. The core problem is that rust forbids two mutable pointers into one chunk of memory. If your tree needs backlinks from child nodes to parents, then you are out of luck.

In what way am I "out of luck"? It's trivial to express a tree, including one with backlinks, in Java.

Rust's mutability rules specifically screw you over here (you can't have two mutable references to the same object, ever); most languages (including Java) don't have those rules.

I sometimes wish I could have a mode of Rust where I had to satisfy the lifetime rules but not the at-most-one-mutable-reference-to-an-object rule.

Post reply on HN