8 ms·
Can't happen fast enough. For the last two years in a row I try Rust every 6 months to see if it's at a place that I would consider using it. I hit the 3 proble
by mtanski 10y ago
Can't happen fast enough. For the last two years in a row I try Rust every 6 months to see if it's at a place that I would consider using it. I hit the 3 problems described here every time I try it. You can work around all of them by restructuring your code it's just so tedious. I rather be doing something else versus working around this.
The community hasn't really been helpful, the answer is always restructure how write things. I'm writing a column store query engine (with table blocks accessing them by columns) that leads to a lot of borrowing so the advice is not all that helpful. I want to like Rust, but I can't.
- TillE 10y agoI've also found that basic problems like how to implement typical data structures (without unsafe code) are controversial, difficult, or actually impossible. That's really not good. Still optimistic about Rust. But it has some fundamental issues to solve before it's generally usable.
- Gankro 10y agoYou can express data structures safely perfectly fine in Rust as long as you do all the things that make them safe in every other language -- aggressively garbage collect, indirect, and runtime validate. I'm not aware of any language that lets you implement an interesting high performance data structure totally safely. Heck, Rust is impressive because you can encode singly-linked-stack and binary-tree-without-parent-pointers efficiently and safely without garbage collection! You can even build iterators that are statically verified to iterate over every element at most once, and statically guaranteed to not be invalidated. Type systems that are powerful enough to ensure the safety of even moderately complex designs (doubly linked list, tree with parent pointers, singly linked stack, hashmap) appear to be unwieldy and relegated to academia.
- catnaroek 10y ago> even moderately complex designs (doubly linked list, tree with parent pointers, singly linked stack, hashmap) In other words, imperative data structures? My experience with implementing custom data structures in Rust: (0) Purely functional data structures: You don't even need borrows to express them. The main downsides are: poor locality of reference, inability to parameterize the data structure over whether its nodes are uniquely owned or reference counted. HKTs would fix the latter. (1) Imperative data structures: Not even mutable borrows will help you. You just need to drop down to `unsafe` code.
- Gankro 10y agoMore or less. Hence why high performance data structures are invariably unsafe to implement in every language if they can be implemented at all. Rust lets you implement them, and for almost all of them you can even expose a safe high-performance interface to them. The only major exceptions I know for interfaces are * intrusive data structures that just blindly point to random data lying on the stack or stored in other types (a construct like C++ move constructors is necessary to safely manipulate these). * priority queues with high-performance decrease-key (you effectively need to hand clients a pointer to every node, that they can always pass back to you to deref and update the structure from -- this is unsound if that node has been popped and you aren't using a GC scheme).
- eridius 10y agoI have no idea what a "priority queue with high-performance decrease-key" is, but from your brief description, you can't replace the "pointer to every node" with a RAII value that keeps the node from being deallocated?
- pcwalton 10y agoLet's not exaggerate the problem. First of all, non-lexical lifetimes have nothing to do with doubly linked lists (what you're referring to). Second, the language is clearly generally usable, as evidenced by the hundreds of thousands of lines of code written in it, most of which was written by people who have never touched the compiler. The reason is simple: most people get by just fine with the rich set of generic collections available in the standard library and on crates.io. For cases in which those aren't sufficient, you write unsafe code or use Rc. Nobody claims Golang is "generally unusable" because you can't implement your own generic data structures. That it's harder than in unsafe C or C++ to implement doubly linked lists in Rust is just a less severe version of the same kind of thing.
- rectang 10y agoI'm just learning Rust and this is the primary question I have: If I can't use the data structures I'm accustomed to (because of mutability issues), what are the alternatives? Where are the articles describing those alternatives? I've seen a lot of interesting discourse about the low-level stuff (e.g. error handling), but not higher-level "start here" approaches.
- deleted 10y ago[deleted]
- bsder 10y ago> If I can't use the data structures I'm accustomed to (because of mutability issues), what are the alternatives? You can use the data structures you are used to just fine, thanks. Just because everything is immutable by default doesn't mean everything is immutable all the time. In addition, any "unsafety" is generally buried deep inside a library and contained properly. Yes, if you are trying to implement something like a ConcurrentSkipListMap, you're probably going to have "unsafe" in your code (and probably some assembly language). But, if you are using the library, probably not.
- rkangel 10y agoImplementing data structures is considered an 'advanced' topic in Rust. That's ok for two reasons: 1) The data structures you'll need for most scenarios are in the standard library. The data structures you'll need for pretty much every scenario anyone has ever encountered in Rust are on crates.io. It should be relatively rare that you need to write one. 2) Writing data structures IS an advanced topic. The fact that you have trouble with the borrow checker trying to implement them highlights that understanding data ownership can get very complicated. Plus there's usually lots of corner cases to get tripped up in (I can't tell you how many times I've had to debug issues causes with crap implementations of circular buffers in C). And when you do need to write a data structure - unsafe is there to allow you to do it. And given Rusts type system, you can write that data structure once, make REALLY sure you got the unsafe bits right and then hide it behind a beautiful abstraction and never think of it again.
- steveklabnik 10y agoI always wonder about patterns like this, and how they arise. For the kind of Rust code I personally write, I can count on one hand the number of times I needed to deal with a non-lexical lifetime. But it's clearly a pain point for a lot of people, so I wonder where the difference is.
- burntsushi 10y agoI run into it infrequently (in particular, kibwen's example), but it's like a mosquito bite. "Oh, yeah, that sucks. Ah well, it's not going to stop me from doing what I was going to do anyway." It's definitely a little weird to hear it's preventing someone from using the language, so I too would like to hear more.
- GolDDranks 10y agoI can imagine it's preventing someone from getting _into_ the language in the sense that if you run into such a situation, you don't have the mental tools to solve it, and it won't feel just a mosquito bite but worse. Even if you manage to solve it, there's the nagging feeling that there might be more annoying hurdles to overcome – but you don't know yet, so you are prone to give it up and use your time for something else.
- comex 10y agoI bet it's to some extent an emotional thing, if you're an experienced C++ programmer. "Argh, yet again the stupid borrow checker is complaining about something I wrote that would have would work fine in C++ [which I'm used to]! Now I have to rewrite it for no reason." It feels suffocating. Most of the time, it's because the code pattern you tried to use is safe but fundamentally not expressible in Rust's type system (often due to simultaneous mutability), and you need to switch to a different one - which is annoying, but gets less common as you get more Rust experience, and hey, even if the borrow checker feels limiting, it's the state of the art: nobody has done better, you're living in the future. Occasionally it's because your code is actually wrong and would crash in C++, and that really makes you appreciate Rust. But sometimes, quite often in fact, it's something entirely local to one block of code that the stupid thing should be able to determine is safe, but can't, because it's stupid. And that's when you flip the table. That's when you question your decision to use Rust. It's like dealing with buggy software: far more annoying if the thing you're trying to do is supposed to work but broken, than if it just isn't supported. It's not the future, just a profusely bleeding edge. Non-lexical lifetimes solve only a subset of that last category, but a significant subset.
- blaisio 10y agoI'm surprised you keep encountering these problems. I've written a few significant (>1000 LOC) Rust programs and never encountered them.
- bsder 10y ago> The community hasn't really been helpful, the answer is always restructure how write things. Um, what alternative should there be other than "the compiler should magically figure it out"? Every language has specific idioms that are the way you fix "Issue X"--the Gang of Four book, for example, is effectively an inventory of idioms to deal with C++ weaknesses. You may be correct in your assessment that Rust is "too mentally expensive" for your task. That's fine. Rust has a very specific target, and that target is systems programs like kernels or Firefox--large programs that have long lifetimes and complicated memory management. So, for example, if your program restarts processes often, then memory issues pretty much go away, and Rust really doesn't buy you much. If you can tolerate garbage collection, then there are probably much more expressive languages for the task. I like Rust, but I'm really only going to consider Rust when I'm thinking "C or C++". If I'm thinking Python, Ruby, Go, Swift, etc., Rust probably isn't on the plate for now.