12 ms·
I really want to like rust but it seems so very complicated. C++ is too but I have been growing with it. It has been my primary language for 27 years.
by galangalalgol 5y ago
I really want to like rust but it seems so very complicated. C++ is too but I have been growing with it. It has been my primary language for 27 years.
- larschdk 5y agoI often feel the same, and there is certainly a bit of learning curve, but in my experience, all the time you spend battling the compiler in Rust is time saved from debugging in C++, several times over. I'm repeatedly surprised by how my code just works when it finally compiles. It's like the compiler is telling you, "you just made a bug".
- skohan 5y agoJust to give an alternate viewpoint, I'm currently writing most of my code in Rust, and while I am generally a fan of the language, and a huge fan of the tooling and community, I think Rust often gets a pass on complexity because it's mostly compared against C++ which is itself a monstrosity. There are many, many other languages to which Rust seems insanely complex and difficult to program in by comparison. I think that often gets blamed on accommodating the borrow checker, and Rust's low-level nature, but I think a lot of it is avoidable.
- steveklabnik 5y agoI'm curious, not saying you're right or wrong: what bits do you think are avoidable? Personally, I agree that Rust is complex, but almost all of that complexity is inherent to the kinds of tradeoffs Rust makes. With different tradeoffs, I can certainly imagine a much simpler language, but it's less clear to me what stuff could be significantly simplified without doing so. However, I am extremely biased!
- skohan 5y agoMy go-to example would be the module system: 1. 90% of the time, rust module layouts are basically a copy of the file-system heirarchy, so why do I have to type this? This system would be much more approachable if it gave the file-system hierarchy as the default module layout, and let you override it explicitly. The argument I have heard against this is that some people like to comment out module declarations during debugging. I don't find this compelling, because I don't see why you couldn't have an explicit way to ignore a module instead. This is just one of many cases where Rust seems to prioritize the edge case at the expense of the common case. 2. On top of requiring a lot of boilerplate the module system is quite esoteric. I've had to learn it twice: a few years ago I was dabbling in Rust, and I remember having to struggle a bit to understand how to add a second file to my project, and then about a year ago when I was getting back into rust I found it unintuitive a second time. I challenge you to find someone who is unfamiliar with the module system, and see how long it takes them, using only the documentation, to figure out where they have to put the `mod` declarations to add nested submodules to their project to make it compile. Maybe I am unreasonably thick, but I don't think it's my problem since I've worked with a lot of languages, and never had this much trouble. 3. This esoteric system isn't even deterministic. Imagine I have the line `mod foo` in my `lib.rs`. Where can I go to find the source for that? Well, it depends. It could be in `src/foo.rs`, or it could be in `src/foo/mod.rs`. And let's say I'm using external crate: `use some_crate`. Which import does that correspond to? It could be: `some_crate`, or it could be `some-crate` in my `Cargo.toml`. You just have to kind of know all of these implicit behaviors of the compiler to know what's going on. So this is just one feature, but IMO it's just one example of a case where Rust puts very little emphasis on the UX and understandability of the language.
- steveklabnik 5y agoCool thanks! This is a great example of my mental bias, actually: I don't tend to think of the module system as a "language feature" even though it clearly is! There are some good reasons and interesting arguments around all this, but given that I was just curious about your opinion, I won't bore you with all that :) Thanks!
- skohan 5y agoNo worries, happy to share!
- iudqnolq 5y agoI definitely think you're right that the module system is complicated, even the new module system. I would like to make one nit though: it's definitely deterministic. Deterministic just means it can be predicted, not that you specifically can predict it. If the module system was non-deterministic that would be a much bigger issue
- skohan 5y agoOk fair enough, that is true. I guess it would be more accurate to say that a module declaration is ambiguous with respect to the file-system location of the code it's referring to.
- skoodge 5y agoI'll chime in and say that for me at least, the module system was a hurdle at the start and coincidentally the only part of the language where the explanation in The Book (which is excellent, so thank you, btw!) did not click for me. I think it's debatable whether the module system really is complex or just different from what newcomers are used to (and by now I've grown pretty accustomed to it). But in contrast to most other language features, where it was clear what I was getting in return for the steep learning curve, the module system seemed overly complicated at the time for no real benefit. Not a big issue by any means and I would choose Rust with its module system over the alternatives most days of the week, but it is one tradeoff that to me at least seemed orthogonal to the other borrowing-related complexities. (What is more worrying to me nowadays is the whole async story. I do hope that some of it will get better once certain features land and it is certainly an area where some additional complexity is unavoidable, but it is the only part of Rust that I dread touching despite heavily using async in a moderately sized personal project due to the need for WASM + IndexedDB, simply because lifetime issues become much more tricky once async and either traits, recursion or closures are involved. By now I am consciously trying to limit any async parts of the program to a simple and stupid "Rust-light" style without any "fancy" features such as traits or closures, which does not feel like a proper solution. So yeah, in general I agree with you: Rust is certainly complex, but for the most part not unnecessarily so.)
- estebank 5y agoYou might be interested in taking a look at and potentially participating in the "Async Vision Document"[1] which is an exercise the team is going through to collect feedback about the current state of the ecosystem and what the pain points are, as well as a way to lay doing what the desired future state of async Rust should be[2]. The process is happening, as you would expect, in the open and there's still time to influence it[3] if your concerns aren't yet addressed or even mentioned[4]. [1]: https://rust-lang.github.io/wg-async-foundations/vision.html https://rust-lang.github.io/wg-async-foundations/vision.html [2]: https://blog.rust-lang.org/2021/03/18/async-vision-doc.html https://blog.rust-lang.org/2021/03/18/async-vision-doc.html [3]: https://github.com/rust-lang/wg-async-foundations/pulls https://github.com/rust-lang/wg-async-foundations/pulls [4]: https://github.com/rust-lang/wg-async-foundations/issues https://github.com/rust-lang/wg-async-foundations/issues
- ncmncm 5y agoIf you ever find yourself spending time "debugging in C++", you are Doing It Wrong. Coding modern C++ right is the same, that way, as coding Rust: when it compiles, it works. (In general, if you find yourself inventing falsehoods about other languages to promote Rust, you are Doing That Wrong, too.) I have personally spent more time, summed over the past decade, preparing bug reports against Gcc than in debugging C++ memory-usage faults. But C++ compiles faster. Coding Rust is fun in much the way that Forth is: it is a charge to figure out a way to achieve a thing; you know it will ultimately be possible, and when you find the way, it is an ego boost. You could say, "Rust is the Second Programming Religion", and who could ever honestly disagree? (But watch extremists downvote this to oblivion anyway.)
- skohan 5y ago> it is a charge to figure out a way to achieve a thing; you know it will ultimately be possible, and when you find the way, it is an ego boost. This is actually something I agree with, even as a fan of Rust. Sometimes I wonder to what extent the appeal of Rust is based in the fact that you get to feel like a CS undergrad again, climbing mountains to make code compile and run
- linkdd 5y agoIt was my understanding that the memory model of Rust is inherently different than C++'s. Genuine noob question: can you really compare Rust's borrow checker and lifetime management to the smart pointers in C++?
- steveklabnik 5y agoYou can compare them, but the comparison won't show that they're equal :p C++'s smart pointers have direct analogues in Rust, though there are some differences. (unique_ptr<T> and Box<T>, shared_ptr<T> and Rc<T>/Arc<T>) The borrow checker is something else completely. The closest analogue in C++ is the https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines, which offer some similar kinds of checks to Rust, but don't attempt to go nearly as far as Rust does.
- 5y ago
- torrent 5y agoAfter your battle with the compiler is over and it compiles it does not mean your program is correct! If you now what you you have no issues with C++. It's not the language. It's the design, approach and attitude
- linkdd 5y agoWhile I agree that Rust is complicated, this example from the test suite is really a bad example because it's there to test the edge cases of the grammar to ensure backward compatibility.
- smoldesu 5y agoIf you've been working with C++ for over 27 years, you owe it to yourself to at least try Rust. A lot of the features in it are designed to ergonomically operate around the limitations of compiled languages, while also encouraging the developer to write "correct" code. If you've got some spare time, I wholeheartedly encourage giving it a try!
- pornel 5y agoThis is not the same kind of complexity. Rust mostly reflects complexity of its domain (thread-safe, memory-safe, low-level without runtime, a lot of correctness enforced at compile-time), rather than unfixable baggage of C and C++'s early design decisions. I'm not saying all the complexity of C++ is its own fault, but Rust shows how much of it is unnecessary. It manages without any constructors at all (think how many rules and features are connected to them!), without inheritance, and with only one (1!) way to initialize a variable.
- mbStavola 5y agoPick any language and I'm sure someone can point you to a test suite like this, it's not really indicative of a complexity problem in Rust.
- rkangel 5y agoOne thing that people say is that "Rust frontloads your problems". C++ might be a bit easier to get your head around to start with, but as the complexity of what you're building grows you will discover the 'joy' of debugging segfaults and race-conditions. Rust has some type-system complexity to get your head around. It's not as painful as it looks (when you're just reading it rather than trying to do it) but there is a hump of understanding there that you have to get over. Once you've done that though, Rust then helps you so much more in dealing with the 'long tail' of difficult problems. Another way of looking at it is that there are a load of things that you can silently get wrong in C++. There are good practices that help you not screw up e.g. you have to learn how to think about who has pointers to what and how long they live. Rust forces you to think about that stuff from day 1 - the compiler requires you to prove to it that everything is good. It's a bit painful to start with, but it's a good thing overall.
- torrent 5y agohaving segfault is the best you can have: it tells you explicitly that something is wrong with your program. in other languages the same kind of error may result in stale data and the GC does not collect the data and the memory consumption grows slowly. You will notice the problem much later. Np language can solve the inability of writing a correct program. Do you believe if your Rust program compiles it is free of errors??
- rkangel 5y ago> having segfault is the best you can have: it tells you explicitly that something is wrong with your program. If you get one. In Rust if I overrun the bounds of an array I will get a panic. It is deterministic and specified, and the stacktrace will tell me which array I overran. In C/C++ I get no such guarantees - the behaviour is explicitly undefined. If you are LUCKY you'll get a segfault there and then. For one off the end of an array that's unlikely, particularly if it's on the stack. You're much more likely to silently corrupt some data. The program will probably eventually segfault out, but there's no guarantee it's anywhere near the cause, and it could have done anything in the meantime. If you're on embedded it's even worse - no segfaults there at all. No, if my Rust program compiles it is not necessarily free from errors. It is almost certainly free from memory errors though. Memory errors are problematic, hard to debug and the largest cause of security holes.
- kortex 5y agoI learned in this order: C, "C++" (very C-like, just enough to write arduino stuff), rust, and the "real" C++14. Unless you write C++ like C with classes, which is not really writing C++ at all, Rust is actually simpler, easier to learn on your own, more consistent, with better compiler error messages, tooling, documentation, etc. Your situation - boiling frog analogy - is a very common case but also the only one in which case C++ feels less complicated, simply because it's familiar. Everything about C++ feels overwhelming, with so many decisions and degrees of freedom at every step, from build system, to lifetime management, mutable state, concurrency, and threading, to libraries, to dependencies, to deployment. It often feels easier, especially for beginners, because there are so many ways to silently do the wrong or suboptimal thing.
- tisker 5y agoI've written tons of Rust and C++ over the last 6 years, both in the context of large, complex codebases with hard real-time performance requirements. I've also managed teams where I've had to 'train' new engineers and I can say that it is categorically false that Rust is easier to learn than C++, it's not even close. From my experience, it takes any new engineer, even if they have significant Rust experience, at least 3x the amount of time to get comfortable with a new Rust codebase than it does with a new C++ codebase. BUT, once you get past a certain stage of complexity, and everyone gets accustomed to the Rust codebase, managing the Rust codebase becomes a lot easier than the C++ one.