Hacker News new | ask | show | jobs
by saghm 1298 days ago
> Take a look at the standard hashmap implementation (https://doc.rust-lang.org/src/std/collections/hash/map.rs.ht...). Notice the lifetime annotations everywhere. This is a relatively basic data structure, but it has a ton of visual noise due to the constraints of the lifetime and borrow model, and programmers must know, understand and be able to reason about these constraints when using this data structure.

I'm honestly not sure what you're referring to with this example. The lines you linked to have no lifetime annotations, just generic type parameters (which I expect you'd see in most statically typed languages for a type like this), and from scanning down the file, the only places I see explicit lifetime annotations other than the anonymous lifetime (i.e. '_) are in documentation comments until the iterator implementation. I already think that the somewhat common argument that Rust makes implementing data structures isn't really that meaningful (because despite implementing hashmaps and linked list being common CS homework assignments, it really isn't common for most programmers to do at their jobs), but I'm not sure that you can even make that point with regard to lifetimes here. If anything, I think being able to do almost all of the hashmap implementation without needing to explicitly name a single lifetime makes the opposite point, which is that you can actually go surprisingly far without needing to use lifetimes at all and that even an intermediate level understanding of how to use them will cover a large portion of the cases where you absolutely can't avoid them.

Lifetimes can definitely be confusing, and sometimes the syntax for them is verbose enough that it can make it hard to understand what's going on, but I don't think they're quite as big a roadblock as they might sound from your comment. Even when you do have to use them, there's a dirty hack you can use if you're absolutely stuck (assuming you're writing safe Rust; unsafe is a whole other can of worms that I think you can make a good case about with regards to data structure implementation, but it's also even less likely that you'll need to use it than explicit liftetimes): the compiler only requires explicit lifetimes because brute forcing the potential lifetime combinations to see if any is valid is extremely inefficient, but you can always just try the different combinations yourself. Because the whole point of providing explicit lifetimes is that the borrow checker can easily verify whether the ones you provided are correct or not, you don't actually have to be able to tell yourself! By definition any lifetimes that the compiler doesn't give errors on are correct, so if you find something that works, you can move on (and maybe later ask online for someone to explain why it works if you're curious, or come back later yourself when you feel more confident in your understanding).