20 ms·
Why is Rust difficult?
- Animats 9y agoRust's problem is not correctness. The borrow checker is the good part of the language. It's feeping creaturism. The language started out as imperative, and then became semi-functional. It started out as thread-oriented, and now is acquiring "green threads"/coroutines/cooperative multitasking. The generics system and library started where C++ and Boost left off. The "trait" system was more "objects bad, must do something else" than an improved idea. The Go guys knew when to stop. The Rust guys don't.
- timClicks 9y agoThis is a misnomer. This hasn't been an issue since 1.0. Before then, the language designers specifically warned people that they were taking the time to learn what works together. Lightweight threading isn't being re-added to the language. It might emerge from some of the asynchronous I/O work, but that's part of a third party library.
- Manishearth 9y agoEr, no, Rust started out pretty solidly as a functional language. It used to look like an ML variant, with purity and stuff. And it had a GC. It's lost most of that now. It also used to have green threads up till 1.0 (they were removed pre-1.0), we're now adding them back. And they're being added back as a library, not as part of the language. It moved away from both of these.
- deleted 9y ago[deleted]
- eptcyka 9y agoIt's not getting green threads per se, it's getting co-routines. Even then, the co-routines will be mostly a library feature rather than a language feature. As for the distinction between coroutines and green threads - coroutines explicitly yield whilst green threads can be pre-empted. Implementing coroutines without a runtime is hard, implementing green threads without a runtime is harder.
- stmw 9y agoGood article, although there are also some unforced errors of what Rust community calls "ergonomics" - many of which have been addressed, and hopefully many others will be soon - that make things more difficult to learn than the absolutely have to be. But author is quite correct that some things are just hard, and if a language is being "honest", it must expose them to the user.
- writeslowly 9y agoI worked on some small learning projects in Rust about 6 months ago. When I got compiler errors related to the borrow checker and concurrency, I found that it was often easiest to look at whatever variable or function the compiler was pointing to, and then ask myself what could possible go wrong that would somehow fall under the purview of the borrow checker, because the actual error messages didn't always point to the root of the problem. I don't have the specific examples anymore, but I think my errors were caused by things like passing around or trying to mutate references created from a data structure inside an Arc pointer or safety issues relating to unscoped threads. At the time, I felt like those things would have been very difficult to debug from the compiler errors alone if I hadn't had past experience with those same issues in other languages (which is what the article says about needing to learn quite a bit about writing programs correctly)
- tatterdemalion 9y agoWhat we could do better than we do today - and your comment about ergonomics alludes to our work to improve this - is ease the onboarding of that complexity we have to be "honest" about. Its a design constraint of Rust that it must maximize user control, but that does not imply that users have to be faced with all of those choices as soon as they first try to write Rust. In some respects I think this article is an attempt at a counterargument to that work (suggesting that it is "dishonest") but I fundamentally do not believe that there is a contradiction between giving advanced users control and making it easier for new users to write correct code before they have a full understanding of the entire system.
- stmw 9y agoIndeed, I used the term "ergonomics" specifically as such an allusion. But I am not sure I read the article as claiming that such efforts are "dishonest", I instead see it as a reference to some other languages and runtimes that run up technical debt for the sake of easy living in the short term.
- sjroot 9y agoI opened this link expecting someone to complain about the difficulty, verbosity, or other issues commonly mentioned by those learning Rust. I was pleasantly surprised! I learned Rust by implementing an interpreter for one of my graduate classes. I really enjoyed it, especially their compiler which continues to become even more awesome every day. If you want to get into systems level programming, or already work at that level, you owe it to yourself to explore this as an option.
- bitL 9y agoIsn't the problem with Rust that it uses crappy pessimistic heuristics (borrow checker) for essentially NP-C problem, causing complaints where code is perfectly OK? IMO interesting design decision but I am staying away precisely because of this.
- tatterdemalion 9y agoDo you stay away from all type systems? This would be an accurate negative framing for any type system, which all necessarily reject some correct programs.
- bitL 9y agoNot really. Just it's super difficult to understand how exactly borrow checker operates and when would it allow program to compile or not, causing all kinds of unpredictable situations and unless you are "black belt"-level, difficulty providing any estimates. Not mentioning loss of morale when you have to fight it every single day.
- tatterdemalion 9y agoThis is not my experience using Rust. I had six months of programming experience when I first tried Rust. I definitely got confusing errors at first, but I grasped the system within a month or two. And that was in 2014 - the borrowchecker and especially its errors have way improved since then! But this is also a very different objection from your initial objection, which was just a statement of fact about type systems for turing complete languages.
- cortesoft 9y agoI do think a lot of the difficulty when starting Rust was all about it forcing you to do everything correctly, even when the 'correctness' wasn't needed for how the program was currently being used. However, my experience learning Rust was that it was pretty easy to work through these things because of how precise the compiler is at describing the issue. I feel like the compiler was my teacher, and it kept on teaching me new concepts to look up in the docs. It was a grind to learn, but not a 'difficult' grind in the sense of getting stuck and banging my head against the same thing for a long time.
- bonesss 9y ago> I feel like the compiler was my teacher, and it kept on teaching me new concepts to look up in the docs. I work primarily in F#, a functional .Net language, which also enforces strict rules at compile time to ensure correctness... With the benefit of experience it's amazing and comforting and lets you reason happily about applications at a higher level. It's on of my favorite parts of the language, TBH. And while I see its strength over time, and see the benefit it gives to code bases, I also know that for your average C# dev used to firing up their app and debugging at run-time, or working in certain ways with their code, it feels like putting on a straight-jacket. It hurts the "first week" story to the benefit of long term concerns. I totally agree: it's forced learning, which makes it a bit of a grind. But damned if I'm not a much better programmer for the effort :)
- pjmlp 9y agoF# is nice, if only Microsoft would actually provide feature parity with C#, VB.NET and C++ tools. I bet C# will sooner copy F# features than Blend, GUI designers or .NET Native will support F#.
- bonesss 9y agoThat response is kinda offtopic for Rust... but: F# is a first class .Net language that interops rather well with the others... If you have some burning need to use Blend or a GUI designer then you can always have a C# shim feeding into an F# domain/core with little problem. It's the same interop story as VB.Net, fundamentally. That said: if you track MS's track-record those technologies and their Enterprise market viability, outside of resume-driven-development there isn't a lot of reason to be throwing hard money at their new shiney shiney... C# lags drastically behind F# in areas not focused on the client: scientific computing, cloud computing, parallel computing, agent/actor systems, etc... Being a release cycle off on the coolest new drag-n-drop tooling from MS is a moderating influence that has created a much better cross-platform story, and OSS story, for F# than C# has ever achieved, despite the scale difference. Oh, and C# has been actively trying to copy F# for many release cycles, including reworking basic language design decisions... It is, however, fundamentally unable to achieve that goal based on the languages overriding design. I'm impressed they're back-working non-nullable value objects, for example, but the language can't give guarantees that ML languages can. Pattern matching is nice, but exhaustive pattern matching is what you want for hard things, IoW. And those deficiencies make C# a non-starter or also-ran for a lot of the BigData, streaming, cross-platform systems you see in big data halls and scientific computing. It's almost like different tools are good for different things ;)
- kumarvvr 9y agoAfter years of using Python, it's been difficult to wrap my head around GO and Rust. I really wish there was a course on Rust / Go for python programmers.
- Jemaclus 9y agoYou're in luck! https://golang-for-python-programmers.readthedocs.io/en/latest/ https://golang-for-python-programmers.readthedocs.io/en/late...
- raz32dust 9y agoThere are several Go for Python programmers tutorials. A google search would throw up many. And it makes sense, because Go is, in my opinion, a good alternative to python as a scripting language. It is faster and safer although slightly more verbose. There are some Rust for python guides as well, but I think it is the wrong approach in case of Rust. Rust is really a more systems programming language. It makes sense to either learn it from scratch, or learn from a C++ background. Even coming from a Java background, I found it easier to just forget about my knowledge of Java and start looking at Rust as something completely fresh. In case of Go, I was easily able to map it to the python and Java concepts I already knew. I think Go has a nice niche where it can replace both Java and python, but not C++. Rust can replace C++, but not Java or python.
- bitL 9y agoGo is IMO much simpler than Rust.
- sillysaurus3 9y agoIs there a way to avoid the true-believer syndrome for Rust? I want to embrace Rust, but everyone ~100% of the time comes away chanting about how awesome Rust is. So much so that it's a bit unsettling. Zealotry in general is bad, but especially in programming: once you identify as an X programmer, you lose out on ideas from Y and Z. Every tool has its flaws, but for whatever reason it seems extremely rare to discuss Rust's. When you try, it's like you're the Pied Piper: your song brings seemingly the entire community scurrying towards you, ready to force-push you why you're wrong and why Rust is awesome. How about no REPL? We Go now. Slow compiler? Check. Performance is nice, and so is parallelism, but it costs static typing. It's a nice tool to have in your pocket as a fallback, but where's the niche? The ecosystem is huge, too: run `du -hs ~/.cargo/` and see how many GBs you're losing. This is a really tough sell on a 256GB SSD. "So get a bigger SSD!" "Yeah but the compiler is always improving" "Yes but real programmers don't really need a REPL" "Yeah but static typing is worth the tradeoffs" These refrains have been identical for nearly a year. Is there anything new to say, or is it time to agree to disagree?
- eridius 9y agoI find it pretty strange to read you say "it costs static typing". Static typing is a feature. There's a reason people are starting to switch to TypeScript instead of JavaScript.
- sillysaurus3 9y ago(ง'̀-'́)ง Static typing is useful in large codebases at big companies because it forces you to communicate your intentions clearly. It's also useful in large OSS projects because it allows your IDE to auto generate tooling and documentation. If someone is using TypeScript, it's far more likely the codebase will have clear, documented interfaces. But TypeScript is optional. It doesn't hold you down and yell at you until you obey it. Even when you're using it, you can simply ignore the warnings/errors if you want to be naughty, and TypeScript will simply shrug and say "if you insist. You'll realize later I was right." But in the meantime your code actually runs. In Rust, it's the opposite. You have to think about every single aspect of what you're doing. Making a cathedral out of toothpicks would also force you to plan your actions very carefully, but you wouldn't really say it's a feature per se. More like the tradeoffs of the medium.
- jadbox 9y agoI feel Go and Rust are great options for writing modern server side applications today, but they exist on two different ends of the spectrum. The Go language is highly minimal, constrained, and forces devopers to write unified code, that performs extremely fast idiomatically. This uniformity is helpful for open source collaboration. Rust is a much more robust language (eg generics), but is more complicated to pick up and harder to read by comparison. Imho, Go is ideal for general web services, while Rust is better for system apps, tools, or complex web services like real-time exchanges or financial systems. This is just a general guideline though in my mind.
- fpoling 9y agoGo does not perform "extremely fast idiomatically". There are a lot of cases where replacing channels with semaphores or atomics, avoiding too many go routines etc. can lead to significantly better performance. But Go does perform good enough if one uses simple idiomatic code style while making things relatively safe and maintainable. That is its huge advantage.
- EugeneOZ 9y agoRust is simple enough for web app needs. It took me about 4 months to start writing code in JavaScript not worse than open source libraries. It took the same time to learn Rust and start writing code, clean and dry enough, with almost 100% tests coverage. Rust gives something Go can't: when you receive warning "variable doesn't need to be mutable", and you know you make it mutable intentionally, you know you just caught huge error (made by human, not compiler). It's just one example, in general I feel compiler is my best friend, always 100% honest to me.
- shmerl 9y agoYou contrast them only by complexity, but the actual reason for it goes further. Go achieves simplicity through a major trade off of using garbage collector. That's a price that you need to pay just for using Go. Rust on the other hand doesn't impose it, following the approach of letting you decide what you want to pay for. This results in higher complexity. So it's good to remember that simplicity of Go doesn't come for free.
- 9y ago
- krapht 9y agoOne of these days I'll get around to Rust. I don't think it's fundamentally difficult, just different from most people's cowboy programming. I'm much more excited these days about program extraction from verified programs written in Idris or Coq, which is on a whole other level of pain and suffering.
- timClicks 9y agoDoes anyone have any experience regarding TLA+. Does it make formal verification at least slightly less painful?
- bitL 9y agoMind you even correctness checkers aren't panacea - they won't go all the way down to check if you are using IEEE 754 correctly and handle all possible edge cases and rather assume "well-defined math properties". And as Donald Knuth used to say: "Beware of bugs in the above code; I have only proved it correct, not tried it."
- jacobush 9y agoMade me think, maybe they should check if you are using IEEE 754 correctly...
- TheDong 9y agoNumeric 'correctness' is a business-problem property. For a game engine, correctness is speed and "right enough". For a research physics simulation, it may be "as right as possible". You can't check whether floating point inaccuracy is correct generically because the definition is entirely dependent on the business needs of the program in question.
- jononor 9y agoOne could enforce the strictest correctness by default, and then allow/require to opt-out in cases where programmer decides it is OK, like a game.
- jchw 9y agoI like Rust so far, but there's a few things I think aren't true: * That Rust is only harder because it enforces 'correctness.' It certainly is harder because it enforces correctness, but it's also harder because of how. I'm not saying there's a better approach to this, but I think a lot of people are implying that there isn't, and I don't think that's a safe assumption. I think that we could find ways to make equally memory-safe languages that go about enforcing safety in entirely different manners than with ownership and lifetime semantics. * In fact, the entire idea that Rust enforces correctness. Only if your definition of 'correctness' to be memory-safety, but I would normally define 'correctness' to include rigorous mathematical proofs. Rust's safety guarantees are often accidentally blown out of proportion; they mainly aid in preventing security and concurrency bugs, but only a certain class of each. This is still useful, but this caveat really needs to be in your face more often, as a lot of people will not mention it when touting the benefits of Rust, and beginners can get easily confused about what exactly Rust prevents you from doing. * The idea that Rust's approach is always worth the trade-offs. Go is another programming language I like, and there are definitely things that are simply easier to write in Go with few disadvantages. Fearless concurrency is a wonderful feature, but for embarrassingly parallel problems like, often, web servers, where each thread is usually independent in terms of mutable state, Go works wonderfully. It also lets you shoot yourself in the foot in a way that Rust wouldn't, but often for a lot of simpler apps it still ends up being easier. * The idea that solving the compiler errors makes you understand the problems correctly. For example, you could always just clone memory at every occasion, return the input instead of borrowing, etc. In fact, these things might be easier for a beginner to do. There will probably be a ton of Rust anti-patterns that come about from trying to resolve compiler errors.
- jacobush 9y agoI agree with everything, just wanted to nuance with a little thought - if cloning memory at every occasion makes the code safer and more correct but slower, that might be worth it. Always favor correct over broken. If you are coming from C to Rust in a domain that is actually better suited for Go... well at least you are arguably better off with Rust than C, right? So I think that Rust will advance the overall state of the art, just a bit.
- singularity2001 9y ago(for newcomers) nothing works out of the box or as expected program[0]="+"; | ^^^^^^^^^^ the type `str` cannot be mutably indexed by `{integer}` error: use of unstable library feature 'collections': needs investigation to see if to_string() can match perf error: borrowed value does not live long enough reference must be valid for the block suffix following statement 0 When you use an index operator ([]) you get the actual object at index location. You do not get a reference, pointer or copy. cannot move out of indexed content
- killercup 9y agoPlease reformat your comment so it's more readable. Adding 4 spaces in front of a line will make it monospace.
- marcosdumay 9y agoOuch. I still couldn't wrap my mind to that string traversing gets intuitive in Rust. The entire iterator thing seems completely counter-intuitive.
- smaddox 9y agoIsn't it basically the same in Go?
- marcosdumay 9y agoI don't know Go, so I can't really tell.
- pornel 9y agoRust is especially difficult if you bring your C-like assumptions to it. You first need to learn difference between a borrow (a view, which may be read-only) and owned type, and know that Rust enforces stdlib strings to be UTF-8. Random mutation of a byte in a string is possible, but it has been deliberately put behind an unsafe function call, and there are better alternatives available (like char iterators). It's not hard once you "get" the way Rust works with data.
- hsivonen 9y agoIt's a good article, but touches on a pet peeve on mine: It bothers me when people who have written C or C++ mention lifetimes as a novel concept. What's novel is that in Rust the compiler cares about lifetimes. As a concept, though, lifetimes aren't novel and thinking about lifetimes conceptually is essential to writing C or C++ that's correct enough that it can be exposed to untrusted input. It's great that the Rust compiler relieves this cognitive load on the programmer compared to C and C++ leaving it up to the programmer to take care of.
- jstimpfle 9y agoYes. And tackling vague conceptual problems by introducing a uniform mechanism and syntax leads to overcomplicated designs. That's from my experience using C++ and other languages, at least -- Rust has always intimidated me so I haven't tried it. Many problems are actually not that hard if we start only with the truly given things. Namely at C level, or even assembler level. For example, I recently had the opportunity to convert a design based on OS threads to one employing userspace threads ("cooperative multithreading"). It was a big success, since the need for synchronisation primitives completely went away, and it was much easier to program than e.g. Javascript -- which requires callback chaining. Any language that can't give as good control as C does needs to build huge infrastructure to support approaches like that (if it at all suits the language's semantics). And strictly, even C is too much abstraction - to support green threads some non-portable parts are needed.
- k__ 9y agoBecause it forces you to handle edge cases. Java is also harder than JavaScript because of this. Yes, the edge cases Rust forces you to handle are different than those of Java and probably make more sense to solve, but I think this is still the root of the "problem". While edge cases are part of "the rule" they feel like exceptions of it. Most of the time you write 80% of the program code in 20% of the time and the remaining 20% eats 80% of the time because of the edge cases. In many cases you can simply ignore the edge cases, because well they will fail, but nobody cares 90% of the time. If the remaining 10% make too much problems, invest some time in workarounds, but 10% of the remaining 20% isn't that much, so this often will cost you also just 10% of the 80% of time. If you can't ignore edge cases in your software, because even a 2% chance of people getting injured is a huge problem, you use Rust and fight with these cases.
- wasted_intel 9y agoYou can also opt to skip handling these edge cases by either copying (decreasing performance) or unwrapping (decreasing reliability). The great thing is that Rust gives you the choice.
- vatotemking 9y agoRust error handling along with the From trait is so good. I've been trying to replicate a sort of similar behavior in nodejs but its not as ergonomic.
- resource0x 9y agocould someone point to the article explaining how Rust compiler reasons about the program, how different kinds of objects and pointers are represented in runtime - in a word, something that would help me grasp what is really going on when I compile and run the program. The tutorials I saw are written in assumption that you don't need to know that. Which makes me feel like a total idiot
- pzone 9y agoThe introductory manual "The Rust Programming Language" is a good place to get started. https://doc.rust-lang.org/book/second-edition/ https://doc.rust-lang.org/book/second-edition/
- dolguldur 9y agoWill Swift ever be able to span all the way down to enable Rust-like performance in places where it’s necessary? Or is it much more that it takes for a language to be a viable choice for starting new C++ type of projects with?
- smitherfield 9y agoTo (potentially) match Rust/C++ performance Swift needs 1. Stack and static-allocated arrays. 2. True pass-by-reference for value types. 3. A sufficiently-smarter compiler that's more often able to elide dynamic allocations, reference counting, bounds checks, vtables etc. (Lifetime semantics will help with this).
- gkya 9y agoA minor problem with Rust is aesthetics. The syntax might look cryptic at times, and error messages the compiler outputs are not everybody's cup of tea, I'd guess. These are certainly not all that important when you're considering it for the actual benefits of the language, but otherwise that is a little con for me. If you write: println!("Hello, {what}!", "world"); in your program, the error message you get is 16 lines long. And there seems to be no option to have terser error output.
- _pmf_ 9y agoIt's similar to learning Stateflow: it has a bigger upfront cost in program design, but once it's fully specified, the implementation will likely be correct (less degrees of freedom).
- dumindunuwan 9y agoWhat you guys think about a documentation like on https://learning-rust.github.io https://learning-rust.github.io . Will it be difficult to learn Rust with this type of documentation?