13 ms·
The struggle with Rust
- grabcocque 10y agoThese kinds of articles are always hostages to fortune. Because I guarantee somebody, any second now, will demonstrate that what the author wanted to do was trivial, and if he'd spent a bit less time trying to start flamewars on Hacker News he'd have discovered it. Not me, by the way, I don't know rust. But I reckon it'll be about three comments down.
- BozeWolf 10y agoIt is already in the comments at the site of the article. To quote "Will": "On the bright side it is possible to implement a pretty elegant solution to this particular problem"
- mpalme 10y agoBut in any case, it will be helpful for other newcomers to Rust because they are likely to run into the same challenges.
- Amezarak 10y agoI think part of the problem is this: if you're say, a C++ programmer, you can write C++ in most other languages and have a working program, even if it's not idiomatic. You can't in, say, SQL, Rust, or Lisp. That doesn't make them a priori harder than other languages, it just requires a shift in thinking, whereas if you're jumping to say, Java after C++, you can get started right away and hopefully pick up idiomatic Java as you go along. Instead of thinking "here's how I would implement this in C++, now how do I translate that to Rust?" you have to cut that part out and think "how do I write this in Rust?" I mentioned SQL because that's where that really, really, clicked for me: if you ever write SQL and think imperatively, you are doing it wrong, you have to think in sets, and once you do that, SQL is the easiest and most natural thing in the world. The Rust Book is pretty good, but I think it would really benefit from an in-depth section early on explaining how writing in Rust requires a paradigm shift in your thinking, and exactly how to think Rust-ically. I'd write something here, but I'm still learning how. :)
- kazagistar 10y ago(SQL is still kinda a crap language for dealing with sets, because the synatx does not represent the order in which set operation are applied or anything else; instead, they went with the "cobol" strategy of trying to make things like english.) But I agree with your premise, certainly.
- steveklabnik 10y agoWe're re-writing the Rust book at the moment: http://rust-lang.github.io/book/ http://rust-lang.github.io/book/ It doesn't explicitly have a section like this, exactly, but there are several "thinking in Rust" style chapters towards the end.
- gcp 10y agoIf this were a C++ problem the author wouldn't have blogged because the answer would've been on StackOverflow.
- sambe 10y agoNot sure if your comment was intended dismissively/jokingly, but I think also somewhat insightful. I find myself much less often really thinking about how to do something these days; if it seems remotely standard or potentially troublesome I google it. As a result, I spend less time thinking "algorithmically" about low-level stuff and probably lose something. But I also spend more time thinking (perhaps algorithmically) about the business domain, and am ultimately more productive.
- jandrese 10y agoGoogling for Rust solutions is dangerous since frequently the advice you find only applied to some old beta version and no longer works. Then you find a second answer but it only applies to an even older beta version. None of the examples anywhere work of course. This is my biggest frustration with the language: the manual is good for what it is, but it only covers the basics. You can see this in the article, where the author tries to implement a simple DNS cache and fails miserably. He doesn't even get to the part where you have a separate thread managing the cache and expiring old entries in the background to avoid unbounded growth and stale data. This is the sort of thing I could whip up in literally half an hour in C, but I just know the borrow checker is going to be a pain in the ass if I try to do something similar in Rust.
- sambe 10y agoAnd your comment sounds exactly like the author to me: "I can't move transparently from languages I know well to ones I don't". Would you be able to whip up same in Haskell or Erlang? How many people claiming this would include a few bugs that Rust prevents? Learning curve is a feature for sure, and the Rust community seems to be aware of this. But expectations of minimal effort are odd.
- killercup 10y agoThat's why I'm really looking forward to the point in time where "non-lexical borrows in Rust stable" and "clippy installable via rustup" converge.
- adwhit 10y agoThese sorts of articles are starting to pop up a bit more frequently, presumably because Rust is starting to get a bit of traction. The theme is "I know $LOW_LEVEL_LANGUAGE therefore I should be able to program Rust. I spent a few days and couldn't. I don't like Rust." Unfortunately, things aren't that simple and Rust really is different from other languages. It takes months of steady investment (and yes, frustration), but the payoffs are spectacular. I would urge the author to persevere. In the meantime, the community is very helpful and I'm sure you'll get lots of useful advice on the back of this post.
- sametmax 10y agoExactly. The fact that rust is easier than most low level languages made the high level language crowd forget than bare metal programming IS HARD. Try to do a big project in C++ or C and you'll see that making something that is production worthy takes months. Besides, as a Python trainer I can make you productive in it in a few days. But it will still take a lot of time for you to be good at it. The only difference with rust is that the first "reward stimuli" comes later down the road because you need to be better at it than at Python to make use of it.
- trishume 10y agoAgreed. Rust is different from other languages in that it is HARD to learn. It took me 3 projects and thousands of lines of code before I finally felt like I'm okay at Rust. Each project involved tons of compiler fighting that I now know how to avoid or solve. The problem is that instead of a general technique for solving borrow checker issues, every issue has a different specific technique. Hash map matches (like the article) require the entry API. Multiple mutable pointers into a buffer require either using a typed Vec or Vec#split_off. Cyclic data structures require an Arena or Rc<Refcell<>>. String casting issues sometimes require .map(|x| &x). Global state requires lazy_static. Nice error handling requires error_chain. When you run into problems with "Send" you need a Mutex. The list goes on... It's like pure lazy functional programming in Haskell in that unlike other languages you can't just pick it up based on previous knowledge and patterns. You need an entirely new toolbox of pure algorithms and data structures, or in this case borrow-safe algorithms and data structures.
- nercury 10y agoYes, it is hard to use mutable shared values Rust. This is exactly the point.
- creshal 10y agoSo how do you avoid it?
- nikbackm 10y agoUse unsafe or wait for the improved borrow-checker?
- nercury 10y agoWell, you either uniquely mutate, or keep the value immutable. Usually you construct the pipeline to switch between these as you need. If you need to share the result from one mutation to the other, you can do it by passing a simple immutable value that communicates the state change to other mutation, but don't try to do both at the same time. This is simply a good practice enforced at compile time. Of course, sometimes these rules prevent some valid cases, but overall it is worth it. If we are talking about HashMaps, the Rust std lib has useful Entry api to for get-or-insert use cases. In rare cases where you need to share the value between different parts of the system, there are primitives you can wrap your value in and enable reference counting, as well as internal mutation (even if wrapper is immutable, it provides safe api for mutation). In cases where the concurrency is needed, there are mutexes, channels, and multiple libraries to parallelize the code (like rayon or crossbeam).
- AstralStorm 10y agoThe problem is there is nothing like "atomic mutable", equivalent of C++ std::atomic with at least sequential consistency. So you get to drop all safety often instead to have shared mutability.
- dbaupp 10y agoThis is wrong. There is a std::sync::atomic module, along with types like Mutex and RWLock.
- gnuvince 10y agoWhen I first learned OCaml (knowing only Python), I swore a lot at the type checker for refusing to compile code that I knew would work at run-time (e.g., a variable having multiple types, but on strictly disjoint execution paths). It seemed insane to me that people would want to subject themselves to this kind of bondage and discipline. And yet, many years later now, I have learned and internalized how type systems work, I have learned not to try and simply replicate Python patterns in OCaml, and as a result I use OCaml to write code quickly and without any headaches; and not only is the type checker no longer an obstacle, it's now a valuable assistant. I believe that we are seeing the same kind of phenomenon in Rust: we are trying to replicate C or C++ code directly in Rust, and we get frustrated when our efforts are foiled by the borrow checker. It's going to take some time and some efforts before we learn and internalize how borrowing works in Rust and how to change the way we write programs so that it is no longer an obstacle. The Rust team looks very receptive to comments about taking away some pain points (e.g., non-lexical lifetimes), but we also need to accept that, for a little while, we are going to feel like we did when we were new programmers and were trying to make sense of these new constraints.
- tejinderss 10y agoNot related to the topic but how do you find ocaml as compared to python or rust? Do you think its worth learning today as opposed to rust for high level general purpose programming?
- njs12345 10y agoIt occupies a slightly different niche to Rust as it has a GC. If you can live with that, it's probably going to be more productive than Rust for you. It's definitely worth playing around with a language from that family. OCaml is maybe slightly more practical than Haskell and it has some nice resources available - in particular Real World OCaml looks really good: https://realworldocaml.org/ https://realworldocaml.org/
- lmm 10y agoIt is well worth learning an ML-family language. In addition to Rust, OCaml or Haskell as njs12345 mentioned, F# or Scala might be options. OCaml is probably more mature than Rust, has more libraries available, and has automatic memory management which takes some of the load off you (especially if you're writing a GUI application, IME). But it's not got Rust's "hot right now" factor, it doesn't have Rust's ease of embedding in other languages, and it doesn't have quite the same focus on high-quality documentation. If you already know Rust I wouldn't bother learning both - they're very similar languages.
- Dowwie 10y agoI spent the last week working with Rust and learning from the Rustaceans. It's been such a great experience. I am really glad that I dedicated some time to it. In a short amount of time, I've already dramatically improved some computationally expensive python code by more then 10x, largely with the help of the community. Further, Rust is already making me a better programmer. If you are skeptical, I challenge you to dedicate yourself completely to a solid week crash course of Rust and experience this for yourself. If you struggle, don't give up and blog about why you hate Rust. Join #rust-beginners on irc.mozilla.org and ask for help.
- justinlaster 10y ago>So I spent a few evenings with Rust I stopped reading. There is literally nothing you could possibly say that'd be worthwhile after "a few evenings" with Rust, especially when you lack the proper background in the first place. This trend of "The problem with Rust: A naive and inexperienced perspective"-esque articles is already old.
- sgift 10y agoI read a bit further, it doesn't get better and my summary would be: Rust isn't C++, doing things the C++ way in Rust is not easy, therefore it requires too much ceremony to do what I want and is too hard.
- bronson 10y agoI made it to > I have a buffer, that I want to mutate using pointers Turns out you were right.
- gcp 10y agoYeah, that entire paragraph is basically a list of all the things safe Rust will not allow you to do. It should be a sign that you're tackling the problem the wrong way around...
- gravypod 10y agoCould the issues of rust be rectified with a better theorem proved that goes past "2 things are touching this"? I don't think I'd mind if the compiler said "your code will not work because eventually it will modify the same bytes at the same time and create an unpredictable state" but I will mind if it says "your not good because you have two mutable references.
- Diggsey 10y agoHaving a more powerful theorem prover is not always better: it makes it harder for the programmer to know whether a piece of code will work, and you can start getting non-local effects, where a change in one part of the code can break a (seemingly) unrelated part. However, what you're asking for is very similar to what types like `RefCell` and `RwLock` do - they effectively delay borrow-checking until runtime. Now you can have references to a `RefCell` in multiple places in the code, and they can all get mutable access to the interior, just not at the same time. Having said that, I find it interesting how rarely things like `RefCell` are needed in practice: there's almost always a better way to satisfy the borrow checker, and it usually results in much cleaner code.
- gravypod 10y ago> Having a more powerful theorem prover is not always better: it makes it harder for the programmer to know whether a piece of code will work, and you can start getting non-local effects, where a change in one part of the code can break a (seemingly) unrelated part. I think there are two solutions to that problem. The first is to involve HCI people in the development in the language to see how they can improve the output and communication from the theorm prover to the programmer. I imagine that, some time in the future, a very powerful therom prover will make its way into a "general" language and will bring some cool effects. The theorum prover I'd like to see will attempt to prove all of the conjectures used in the program and, when not possible, will say "possibly invalid code. Please solve this conjecture" where then this would be given to a mathamatician and they have to complete the missing steps to see if it works, if not we tell the compiler this isn't going to work and it now generates errors for this. The other solution is to limit the shared state of every program using very strict segregation of all moving parts and an attempt to limit use of side-effect-causing operations. This second one is nothing new, I mean the original LISP crowd had these ideas down and theres nothing new. I don't think I've ever worked with a compiler that has a built in theorum prover, possibly a shared library of proven work, and a way to in the language aid the prover. For instance this type of function definition int(int numerator, int denominator) where (denominator != 0) divide { return numerator / denominator } And even more so I've not heard of unobtrusive theorum provers that keep out of the programmers way while still being useful. I think an unproven relation should be a warning. It's not good but the program can still run and you (you being not me but the math-people) can come up after me and prove all of my work or tell me I'm an idiot and to fix it.
- farresito 10y agoWhy this circlejerk about rust being hard to learn and use? I've seen multiple threads like this one in the past week. Yeah, rust is not easy and takes some time to get used to, but I'm surprised this kind of threads come up so often from a community like hacker news. You decided to learn a language that is a bit different than what you usually find out there that requires to wrap your head around some new concepts. You can't expect to be fluent in it in a few afternoons. If that's the case, then learning rust is probably not the right choice.
- deleted 10y ago[deleted]
- camus2 10y ago> Why this circlejerk about rust being hard to learn and use? Dismissing concerns about rust learning curve as a "circlejerk" isn't going to make more people want to learn rust. I thought the rust community was a bit more mature than the Go one and wouldn't fall into this kind of mindset ... > If that's the case, then learning rust is probably not the right choice. Same tired argument I hear from Go folks. "Go wasn't invented for you ...". Extremely arrogant.
- pron 10y agoRust provides something that few if any other languages do: memory safety without GC. It is very obvious that this comes at a non-negligible cost in development effort. If you need what Rust provides -- and an important class of software certainly does -- you should be more than happy to pay that extra cost. If you don't, there are plenty of alternatives. But exchanging effort for rather unique guarantees is the very explicit tradeoff that Rust makes. That few other languages choose to make this tradeoff is what makes Rust so valuable.
- burntsushi 10y agoTo be clear, I think the data supports that Rust comes with a non-negligible learning cost. Whether that cost is continually paid isn't clear yet. (I personally think the answer is "no.")
- pron 10y agoI agree that there's no data, but I would be very surprised if the answer is indeed no, as there are at least good theoretical reasons to assume extra cost. Proving anything (let alone to a compiler) comes at a computational complexity cost (think of the proof as a certificate). In principle, a large number of proofs may be "free" in the sense that no more information than the programmer normally supplies the compiler is necessary. But if this is true in every case, that is very surprising.
- burntsushi 10y agoIt's not very surprising to me. Paraphrasing, "once I got past the initial hurdle of the borrow checker, programming in Rust became much easier," is frequently uttered in the Rust community. I'm not trying to make a very nuanced claim here. All I'm saying is that there's clearly a lot of people who struggle while learning Rust, but that this is very different than paying an eternal development cost similar to that struggle. We should be careful not to conflate them. (I did not meant to get into a broader philosophical discussion about using a type system. That's a different conversation IMO, and I disagree with your analysis because you only focus on the upfront cost while neglecting the maintenance costs in the absence of such proofs.)
- moomin 10y agoThe joke being, this is being written by a guy who has constantly insisted on his blog that if people don't think NHibernate and IoC are a good idea for their project, it's because of their personal failings. Me, I muck around with Haskell. No I'm not productive in it. I don't think that's Haskell's problem, though.
- leshow 10y agoThe first few of these types of posts were OK. But now it's a bit ridiculous. You spent 2 days trying a new language and you didn't like it, your opinion means nothing.
- Etzos 10y agoI don't typically respond to comments like this anywhere, but I think this kind of view is dangerous to have. And it's one the Rust community at large seems to try to shy away from. This kind of attitude towards people trying out a new language is damaging to the person trying the new language and to people who are part of that languages community. The former because it will give them the notion that the community is hostile towards them and newcomers in general and the latter because it can enforce a dogmatic view of the language ("you do it our way or no way!" kind of feel). A language's ability to have people pick it up easily is important. In Rust's case there is definitely always going to be a bit of a hump for people to get over, but the concern put forth in this article seems like a legitimate one, but one the Rust community seems to be aware of. Acknowledging and helping people with these problems (while searching for a way to potentially avoid such a situation for the next newcomer) is important and it's critical that you not simply dismiss someone's opinion because they don't know or understand "the right way to do it" yet.
- threatofrain 10y agoFor a language like Rust that puts all the pain up-front, I want to hear whether the pain is worth it. But someone who spends only a few days can't give you a weighing of whether the pain is worth it. I'm reluctant to even listen to someone's Amazon product opinion if they've only used it 2 days.
- Etzos 10y agoI certainly agree that an opinion piece like this has less weight than one which comes from someone who has spent a considerable amount of time with a language. However, saying that an opinion formed after only a few days is "worthless" is taking it too far. Plus if one completely ignores pieces like this then they are more likely to fall into a rut where pain points like this are forgotten or ignored completely. While the actual pain of getting used to the Rust way of doing things may be harder to mitigate perhaps there is some insight in opinions like the ones presented in the blog here which can lead to a way to help people get over that pain in a quicker/less painful way.
- vbezhenar 10y agoI don't know Rust good enough, but do unsafe blocks help there? Data structures belong to library code and libraries surely can utilize unsafe blocks, because they are expected to be heavily tested.
- omouse 10y agoI know about GDB, that ain’t a good debugging experience I can't take this article seriously after reading that and after reading this: So I spent a few evenings with Rust How long did it take you to learn C, C++, Java, Python, Ruby, Perl or other languages? MONTHS. Many many many months. Sure you could get something up and running in a few evenings but after many months did you realize that earlier code could be better. Each language has its own obstacles and spending a few evenings isn't enough time to get around them. I gave Haskell a pass but after checking out Elm I can see more of its power. I gave Rust a pass because the language was changing but now that it's stable I expect to sit down for a few months at least learning it.
- draw_down 10y agoI agree with him about GDB.
- kernelbandwidth 10y ago> The very same trie code that I tried to write in Rust I wrote in one & half evenings in C++ Use unsafe. No, really, just use unsafe. Clearly a big value of Rust is that it's a safe language, and the design patterns around safety and affine typing are emerging and good. We should want people to write and use safe code as much as possible. But the trie example seems, to me, to be very much the sort of thing unsafe is for. Writing in C++ is essentially doing everything in unsafe. Unsafe is not evil; it's an important part of the language and when it's called for, it's called for.
- Manishearth 10y agoI'm not sure, tries are pretty easy with safe code. It's only things like data structures with parent pointers where things get hairy. If your goal is to use malloc and stuff (which seems to be what the author wanted) then of course you should use unsafe. Unsafe is indeed for doing abstraction-writing like this. Still, you should avoid it if you can.
- drbawb 10y ago>We are talking about allocating memory, in a system level language, and unless you are jumping through hops[sic], there is just no way to do that. To be fair, if you want to call malloc it is still just as accessible[1][2] as it is in C. If you search the Rust documentation for malloc `libc::malloc` is even the first result. If you were to use that on stable Rust the error message will even tell you to link your program to the libc published on crates.io (which is just adding a line in your Cargo.toml file.) I'm not sure I'd call that jumping through hoops. I'd love if Rust provided easy access to its own allocator on the stable release channel; but I'm willing to wait for them to get it right, these things take time.[3] [1]: https://doc.rust-lang.org/libc/x86_64-pc-windows-msvc/libc/fn.malloc.html https://doc.rust-lang.org/libc/x86_64-pc-windows-msvc/libc/f... [2]: https://is.gd/cgkX2R https://is.gd/cgkX2R [3]: https://github.com/pnkfelix/rfcs/blob/117e5fca0988a1b0c4b6e4de83b633f92b0c9c84/text/0000-kinds-of-allocators.md https://github.com/pnkfelix/rfcs/blob/117e5fca0988a1b0c4b6e4...
- Manishearth 10y agoAlso, most folks would use `Box` with `Box::into_raw` (also `Vec::with_capacity` for dynamically sized stuff, which works fine. RawVec is an implementation detail; Vec exposes most of what you need for dealing with raw memory.
- tps5 10y agoI'm not coming from C++, but my experience with Rust has been: * Read the book, got some of the concepts but most of it went over my head. * Did nothing, maybe thought about it a little bit. * Two weeks later: read the book again. It made more sense but some of it is still lost on me. * Actually wrote some Rust. Was hard, frequently consulted the book, the "by example" book, r/Rust, and google. * Two weeks later, it's much easier. I'm still consulting outside resources frequently, but I generally know how to fix problems as they arise and my mental model of the how the language executes is becoming more and more accurate. I've spent on average 30 minutes a day working on a pretty simple Rust program for about a month now. The advantages of Rust so far have been: if it compiles, it works. Extremely easy to refactor: for my main data structure, I've switched between vecs and arrays back and forth probably 4 times to get a feel for the differences. This is generally really easy to do because they both implement the the iterator trait. In the other languages I use (at work), switching between one type of collection and another would be a huge time sink and involve a lot of annoying (though trivial) refactoring. The main advantage of Rust for me (and the reason why I decided to check it out vs go) is that I don't have a lot of experience thinking about memory at a low level. The dynamic languages I work with abstract that away from the programmer. I wanted something that would force me to think about how and where memory is being allocated, and whether I want to pass by reference or value. For someone who has spent a lot of time with C/C++ or just someone with a background in CS/programming languages, this may all seem obvious to you. But there's a lot of programmers out there who learned with dynamic languages and don't have a good mental model for memory. Rust is a good instructional tool for us. I don't really have an opinion on whether Rust is "production ready." It's being developed rapidly though, so I think it'll get there.
- eximius 10y agoIf you just want to allocate a chunk of memory for random use like you would in C, it can't be guaranteed to be safe. So I would hope you need to jump through hoops.
- AstralStorm 10y agoIt is a rust weakness that it does not have "partial unsafe" that guarantees some things. Makes many kinds of code unnecessarily hard to reason about.
- w8rbt 10y ago"multiple mutable references"... I would use C++ for this. I would not use rust if I had a design that required that ability.
- jeffdavis 10y agoWriting libraries, especially implementations of well-known algorithms and data structures, is a bad way to learn most languages. Technically, it's possible, but I think it skews the experience strongly toward languages that are similar to what you've worked with before and languages that are more permissive. I suggest writing applications, or libraries closer to applications (e.g. a specific library that parses a special data format important to your domain), where you have a clear goal but not a clear path to the goal in mind. In other words, hacking. Let's say the author had finished the Trie. What good experience could he possibly have? It's not going to magically run faster than the C++ version or use less memory. It's a well-known algorithm so there probably aren't subtle bugs in the C++ version that rust would have caught. The best you could possibly say is that it was faster to write -- which is exactly why it skews the experience toward familiar and permissive languages. I am trying to learn rust (albeit very slowly) by doing some hacking to make it work better for postgres extensions. I know postgres, and I think it would be cool if it were easier to write postgres extensions in rust. Of course you can today, but you'd have to use a lot of unsafe FFI calls.
- protomikron 10y agoI do not know Rust, but I know C and some Haskell and AFAIK one should building a program in Rust differently than in C/C++ (which is probably the authors background). Get out a quick correct (and this can not be emphasized enough) version (obviously one has to learn the language here) and then optimize (when you have numbers). The author did not seem to get a working version with Rust (sorry, if I am wrong on this), and tried an approach that he knows would work for C/C++. But maybe another approach would have been already performant enough?
- nimmer 10y agoSounds like Nim is what you are looking for: http://nim-lang.org/ http://nim-lang.org/ It's fast, has a Python-like syntas, a good degree of memory safety and optional GC.