11 ms·
Rant disclaimer. Proceed at your own risk. I want to like Rust, if only because anything has to be better than C++. C++ is godawful and it sucks that all these
by benreesman 5y ago
Rant disclaimer. Proceed at your own risk.
I want to like Rust, if only because anything has to be better than C++. C++ is godawful and it sucks that all these decades later it’s what serious big software is written in.
But I haven’t found the explanation of Rust and it’s trade offs and philosophy written by someone who can write serious Haskell and Lisp and C++ and is like “Rust. This is the way. Here’s how and why.”
I’m sure there are much better blog posts than this one that shed light on how parametric as opposed to ad-hoc polymorphism is natural in Rust with no runtime cost. Or how Rust’s nested angle-bracket hell to get a pointer to a piece of memory is actually a deep and profound algebra that exposes std::move for the fraud it actually is or whatever.
Where do I find the explanation of why Rust is less awful than C++ written by someone who has written a lot of C++ out of necessity, doesn’t take non-browser JS seriously, doesn’t think 8 boxes need kube, doesn’t stand to make consulting revenue off having been involved in Cargo, and generally uses C++/Python because they’ve got work to do?
Where do I go to see the light as someone who has some idea how brilliant Eich is and also knows how ridiculous it is to use JavaScript when you’ve got an alternative better than Lua? (I’ve written a JavaScript compiler, I know how unfortunate node.js and Electron are).
I want to be sold! Sell me!
- Glavnokoman 5y agoSounds like you might like Zig. It is not perfect either, but many things are done the proper way there. The only thing I really like about Rust it is that it tries to solve many problems at their roots. It failed in my opinion, but at least it tried to.
- benreesman 5y agoWhat’s the link that takes me down the Zig rabbit hole?
- matheusmoreira 5y agoThe Road to Zig presentation: https://youtu.be/Gv2I7qTux7g https://youtu.be/Gv2I7qTux7g C but with the problems fixed.
- benreesman 5y agoQueued. Thank you!
- devit 5y agoIt's the only language existing that is memory safe and provides zero cost abstraction to the CPU capabilities (i.e. no mandatory GC, values don't need to be boxed, ability to mutate memory). The only limitation that may not eventually be removed is the lack of dependent types (although you can kind of emulate them by lifting terms to the type level and using lifetimes to represent variables). C++ is not memory safe, Lisp has no type system and Haskell has GC, all values are boxed in a closure and it cannot mutate memory safely, so none of these languages are even in contention.
- benreesman 5y agoC++ compiled by clang-12, with clang-tidy and cppcheck turned all the way up, with everything owned by a std::unique_ptr, run through ASAN, UBSAN, TSAN etc (which seems to build about as fast as Rust) lets what by that Rust catches? I’m not being sarcastic, in all earnestness educate me!
- fluffything 5y agoDoes that warn if you do: vector<int> v{1,2,3,4}; for (auto&& i: v) v.push_back(i);
- benreesman 5y agoIn my little toy build I set up no, it doesn't warn me that smashing a data structure while iterating over it at the same time gives UB. I'm 50/50 on if there's a flag for that, don't actually know. Again, in the spirit of becoming more educated, what's the equivalent Rust code? I have `rustc`/`rustup` on my box so I can run that too.
- paavohtl 5y agoThis should be about equivalent. It does not compile, as expected. https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2ebc047ced2efbe897f0a4011e64c22a https://play.rust-lang.org/?version=stable&mode=debug&editio...
- k_bx 5y agoMy favourite three compared to years of Haskell experience are: - runtime predictability. Our async high-load programs are already complex, and having a much more predictable runtime (no GC) makes things feel much more straightforward - lack of bracket need. You get destructors from your types! No more async-exception or other accidental leaks - no exceptions. The “?” syntax is truly genius, Holy Grail of Haskell error handling coming to life
- da39a3ee 5y ago> Where do I find the explanation of why Rust is less awful than C++ written by someone who has written a lot of C++ out of necessity, The O’Reilly book by Jim Blandy and Jason Orendorff. It is a really fantastic book on a programming language, the best I’ve ever read. The new edition is due this year it seems. https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/ https://www.oreilly.com/library/view/programming-rust-2nd/97...
- benreesman 5y agoOrdered. Thank you!
- unrealhoang 5y agoSeconded, this book is so good in demonstrating Rust’s advantages as well as low level programming concepts with its beautiful visuals.
- ahartmetz 5y agoYeah, I also like it better than the official Rust book. My favorite programming language book is still K&R's C book, though.
- tialaramex 5y agoK&R is excellent. One of the things that makes it stand out would be almost irrelevant today, it has an excellent hand-made index. If you're wondering about, say, arithmetic conversions, the index gets you straight to the page which lists exactly what you needed. Wondering when to pick enum over #define? Again, the index has your back. Today online you've got full text search, maybe you find two, three hits that are irrelevant, but it's so cheap you barely care. And in a book today the index is probably auto-generated (hiring somebody to write an index is not a thing these days) and so it's almost useless with dozens of irrelevant entries, but hey, like I said, full text search, so who cares? Because C is such a small language and it was essentially finished when the book was written, they get to do a pretty complete survey while also teaching you, so you read the book once, now you understand C pretty well. The Rust book is much better than C++ books I tried, but because Rust is still immature there are big sections that are being rewritten or have already been rewritten, and of course the whole book can't be reordered and started over each time, so overall it's uneven. I am reluctant to buy a printed Rust book because of that immaturity. My (second edition) K&R is still a pretty good survey of the language. Are there things it doesn't cover? Yes. But few of them are fundamental, whereas I feel like if I bought a Rust book today, in five years it's a historical curiosity like my Stroustrup, except hopefully better written. I still consult my K&R a few times a year, I don't even know where the books I own on other languages (including the long obsolete Stroustrup) are, I might not have unpacked them after moving years ago.
- golergka 5y agoHonest question: what views does one has to have to doesn't take non-browser JS seriously, and at the same time use Python? And what's unfortunate about node.js compared to it?
- benreesman 5y agoPython has (more than one actually) trivially seamless FFI stories down to native (read: C++) code. I personally like `pybind11`, but there are others. Python is basically a convenient way to invoke numpy or Tensorflow or Torch or whatever. It's got numpy/scipy/sklearn/BLAS bindings etc., and is for better or worse how you do scientific computing in the mid-to-upper-mid range these days (the HPC folks have their own whole story). It's a pain in the ass in it's own way, but you're kinda stuck with it if you want to do mainstream ML. As a language it's dumber in some ways that JS, definitely slower in some cases, but also way less weird. Prototype chains and stuff are a cool demo that BE knew about Self and shit in the week he had to write JS, but anyone who claims they like that has Stockholm's syndrome worse than someone who thinks Ruby metaclasses make sense.
- mrighele 5y agoI've been using python for many years, but these days I would prefer to use JS (or better, TS) even for backend. I find it more enjoyable to use than Python, and faster. Sure it has its warts, but if you write idiomatic code they are not much of a problem (e.g. I don't think there is a single class in the code I write, so prototype chains are a non-issue)
- lstamour 5y agoI can say that if someone is sold on Python, you’re not going to convince them to move to Rust but you might convince them to move to Go. Why? Go provides better performance than Python but without the language and keyword complexity of Rust. There’s less language to learn. That said, the more interesting question is TypeScript vs Rust. I can see how the complexity of C++ naturally leads folks to Rust. But I’ve had a hard time choosing Rust over TypeScript when trying to implement a basic service. It’s absolutely true that Node.js web servers aren’t optimized for multi-threaded data access times and the Node.js event loop can get in the way of responsive performance. But at the same time once you build, for example, an HTTP 1.1 web server for Node that is similar to what you’d build using semi-unsafe code in Rust and ships by default in Go standard library, it’s hard to say that JS is any less efficient than Rust when both are generally written to use async/green thread runtimes, make calls using a pool of Postgres or database connections, and either have PG return JSON or otherwise reshape and assign the results to a data model. Given more computing power, Rust obviously wins, but if you’ve a single thread to work with, and a small buffer so after each web request is served, GC can do its thing… where are the tangible Rust benefits besides maximum speed? I suppose I’m cheating by suggesting you could use Actix to power your Node application, but the problem I’m facing is that Rust is really complicated to learn and there are few frameworks that make it easier. The amount of published and shared knowledge there is around Go, PHP, TypeScript, Python and Ruby is enormous. Yes, Rust is clearly easier to learn than all the warts of C++, but it feels like Rust hasn’t gained enough traction to convert TypeScript fans, for example, or at least those building APIs and front ends. I’d really like to be convinced to use Rust because of how easy it is compared to TypeScript but I haven’t seen anyone actually suggest that in practice. Go? Yes, it’s easier to learn than to understand both JS and TS and you can put up with the lack of generics by having more verbose code compared to TypeScript. But Rust? Is it just the case that these other languages are more mature such that all the blog posts have been written? Also note that the hardest problem when getting started in any new language is package and framework selection. Unless you follow a book that has already picked a handful of packages such that you’re happily falling into the pit of success, I recognize that all languages (except maybe Rails or Spring) force the user to make hard choices upfront about their dependencies. But the only book I’ve seen that presents a coherent narrative for Rust APIs is Zero2Prod[1] and I’d feel more confident if there was at least one other similar set of learning materials. 1. https://www.lpalmieri.com/ https://www.lpalmieri.com/ for the book published as blog posts, https://www.zero2prod.com/ https://www.zero2prod.com/ to buy.
- the__alchemist 5y agoFor me, it's the overall experience. Ie: auto-generated docs for libraries, nice package manager, built-in linter and formatter, easy-to-install toolchain[s], high-level coding patterns etc.
- benreesman 5y agoThat's a fair-sounding point. Java had this (but also a bunch of other problems).
- beltsazar 5y agoFor one thing, it's the only non-research programming language that can guarantee at compile time your program free from data races.
- matklad 5y agoIt seems like in your case the easiest path might be to learn how the language works and see it for yourself. Otherwise, I think these posts are roughly in the genre you want: * http://dtrace.org/blogs/bmc/2018/09/18/falling-in-love-with-rust/ http://dtrace.org/blogs/bmc/2018/09/18/falling-in-love-with-... * http://dtrace.org/blogs/bmc/2020/10/11/rust-after-the-honeymoon/ http://dtrace.org/blogs/bmc/2020/10/11/rust-after-the-honeym... * https://gregoryszorc.com/blog/2021/04/13/rust-is-for-professionals/ https://gregoryszorc.com/blog/2021/04/13/rust-is-for-profess...
- benreesman 5y agoBookmarked. Thank you!
- stevenhuang 5y agoThat last article is a great comprehensive summary of Rust's features. Will be passing that around, thanks.
- simias 5y agoWhen my Rust code successfully compiles, it usually works. Frankly in terms of user experience it's selling point #1. I could talk about the borrow checker, trait-based generics, native build system and dependency management, performance, relative ease of writing multithreaded code etc... But thinking about it the thing I like the most about coding in Rust is how hard I can lean onto the compiler and type system to spot mistakes and let me know about them. C++ is not even close in that respect. Duck typed generics, lack of borrow checker, lack of sync/send markers for multithreaded code, easy-to-abuse overloading (that's even abused in the standard library, so there's no escaping it), legacy cruft that springs up in unexpected places, non hygienic macros, exceptions and frankly I could go on for quite a while. I think for some of us Rust is effectively the promised land. I learned some Lisp and Haskell but I could never really get into them seriously because despite some cool language features I just don't like paying the performance costs of a heavy runtime, dynamic typing and garbage collection. So instead it was C and C++ for better or worse. But then Rust came out and said "hey, how about having your cake and eating it too?" and I never looked back. But of course many people don't share the same objectives. If Haskell and Common Lisp are what you consider to be your baseline I can definitely see how Rust's very strict type system would be seen as an annoyance, especially if you don't mind paying some runtime performance cost for the sake of simplicity and speed of development.
- benreesman 5y agoYou seem like someone who could write the blog post I'm looking for.
- simias 5y agoI appreciate the encouragement! Maybe I will, but first I need to write a custom blogging system. In Rust of course.
- secondcoming 5y ago> When my Rust code successfully compiles, it usually works. I think it was on a previous HN story where Rust programmers claimed that to get around borrow checker errors they just clone things. Now, the code may compile and technically be correct, but it hardly exemplifies the attention to detail normally required by a systems engineer.
- stagger87 5y agoPresumably you've read enough to know that memory safety and UB are Rust's biggest selling points? If that hasn't convinced you already, I'm not sure what would. Just keep using C++. (I use C++ and I love it.)
- benreesman 5y agoI have forlorn hopes that Rust will fix build times and I'll tolerate the abusive relationship with the borrow checker if it can move the needle on that.
- firethief 5y agoFighting with the borrow checker is just a phase you have to get through, it will click. The need to write anything that can't be done without unsafety is rare (probably never unless you are writing a data structure library).
- monoideism 5y ago> UB Undefined behavior? As in, you can confine it to `unsafe`?
- tialaramex 5y agoUnsafe Code isn't allowed to have Undefined Behaviour either. What unsafe does, is it says to the compiler: "Hey, I know you're just a dumb machine, and you couldn't prove this code obeys all the rules that keep Rust safe, but I am very smart and I promise it actually is safe". You're also encouraged to explain yourself (to other humans, not the compiler, this isn't Wuffs) so that anybody else maintaining the code can see why exactly you believed this was OK. Over the years, some code which was once unsafe in Rust no longer needed an unsafe block, because Rust's compiler got smarter, "Oh, I see why this is OK". But if your unsafe code has Undefined Behaviour that's actually a serious bug, it's not what unsafe is for at all.
- monoideism 5y ago
- grok22 5y agoThe column for the Rust language on this page (https://scattered-thoughts.net/writing/how-safe-is-zig/ https://scattered-thoughts.net/writing/how-safe-is-zig/) with the rows of "compile time" for various memory issues is what is selling me on Rust that I am spending time with it hoping to sacrifice some difficult current learning time and some future tedious development and compile time to save on painful debug time for some kinds of issues. The problem is that the pay-off is at the end :-).
- cletus 5y agoSo what I like about your comment is you’re clearly more pragmatist than zealot or ideologue. So I don’t know Lisp or Haskell. I never learned in the college years when I might’ve had time and now I just don’t want to pay the years long learning curve. I’ve got shit to do. But the big problem (for me) is I’ve completely turned off dynamic typing. Python did this to me and i I honestly don’t think I’ll ever go back. I refer to dynamic typing as “unit tests for spelling mistakes”. YMMV. Another issue is I like simple grammars and relatively opinionated languages. I’m not the biggest fan of GC either. Years of tuning GC pauses of JVM have soured me on the boundless benefits of GC. I give this as context to say that I like Go. You can learn Go in a really short amount of time. There’s usually only one way to do things in Go. That’s good. Less surprise and less arguments in teams. An issue I have with C++ (and this applies to Lisp and Haskell too) is it allows people to be too clever for their own good. Look at 200 lines of Lisp and there might be a C compiler buried in there. Who knows? That might demonstrate the power of the language but is usually counterproductive to a team or project. So memory safety is the big selling point of Rust. You need to buy into that and why things like static typing are good even though you might struggle with the type system and borrow checker at first. Is better to fight the compiler than be surprised by the runtime (IMHO). But Rust of course is not issue free and it differs from some long-standing and unfortunate design choices early in its life that are going to be hard to correct. Build times are a big one. See this [1] for more. For the last few years I’ve written Hack (aka PHP) professionally. One thing one comes to really appreciate is cooperative async-await, which is pervasive. Writing C/C++/Java has taught me that of you every manually spawn a thread you’re going to have a bad time so you should do anything in your power to avoid this. Go is one flavor of alternative. Hack is another. I’m not sure I’ma big fan of Rust’s. Ultimately, with Rust out any other language for that matter, you need to learn and buy into the idioms otherwise you’re going to have a bad time. [1]: https://pingcap.com/blog/rust-compilation-model-calamity https://pingcap.com/blog/rust-compilation-model-calamity
- atoav 5y agoI had an awful time when I started using Rust because I had a strong (object oriented) view of how to structure my code. At one point where nothing seemed to work and I didn't manage to get anything to compile I just was like: "ok, I give up Rust, I will do it your way". From then on everything worked surprisingly easy. The 3 main things that make Rust great (besides thenusual selling points) are IMO: - the library manager/dependency managment is great - Even if you are never gonna use Rust again, some of the lessons you have to learn when learning Rust are universally useful. Thinking about ownership and race conditions the Rust way will certainly help you tackle some parricularily hard issues with multithreaded code in other languages as well. - The amount of things you can rake as a given within Rust code is very high. If it compiles it usually works. If it doesn't it gives helpful indications why. These indications help you to understand your code better.
- giantandroids 5y agoAfter years of dynamically typed / interpreted languages, I decided I wanted to learn a statically typed language and so I to set out to trial both Go and Rust. Rust was a painful experience. I kept trying to pass around simple types and constantly hit compiler failures. I then set up Go and got started. Fell in love with it, I was immediately 10x more productive then I was with rust. I also found reading other people's code far more easier as well, where rust would have all this (for me) difficult syntax. I want to like rust, but I honestly don't think I am smart enough.
- deleted 5y ago[deleted]
- lalaithion 5y agoComing from dynamically typed high level languages, you're learning two things at the same time when you're learning rust: 1) Low level programming 2) Typed programming Both of which are difficult. I would suggest learning one of Haskell or Scala and one of C or C++ first, and then trying Rust again.
- 5y ago
- benreesman 5y agoFor a post that started with "Rant Disclaimer", this has generated kilobytes of useful, insightful responses, and I'm going to be looking for spare time everywhere I can find it to follow up on all the great resources. I do intend to reply to everyone's comments, but the 20 of you are outrunning the 1 of me on that. If it takes me a few hours to reply thoughtfully to your thoughtful replies please bear with me.
- steveklabnik 5y agoWhile some people complain about the Rust community being evangelical, you'll find this is common. We've built a culture of helping answer questions, sometimes to the point of being too enthusiastic about it. If you ever need help, jumping into the forums or various chat platforms will usually get you a courteous answer in minutes. We aren't perfect, but this is one of the aspects of the Rust community I'm most proud of.
- stouset 5y agoTo be completely honest, I think you’ve had a bigger impact than most in making the community that way. You were a huge boon to the Ruby/Rails community, and you’ve taken that experience and been instrumental in building a helpful, enthusiastic, and friendly community around Rust. One of these days I hope our paths cross so I can buy you a drink.
- steveklabnik 5y agoAw shucks, thank you! That’d be great. Someday!
- GuB-42 5y agoMaybe Rust is not for your project, it is not a universal language, far from it. It is a language designed to make a web browser, and some projects have similar requirements, which makes Rust good for these projects too, but for some others, well maybe the much hated C++ is just better. There is a good reason why several programming languages exist.
- gameswithgo 5y agoRust gives you c++ runtime performance with compile time memory and data race safety. that is about it. less warts syntactically just by being newer.
- sanderjd 5y agoPersonally, I became interested in Rust through early writing about Servo, a project driven by people who were frustrated by writing a lot of C++ out of necessity (in the Firefox codebase), which reminds me of what you're looking for here. Maybe you can dig up some of that writing, though it may be pretty out of date now.
- jkarneges 5y agoYou basically describe me. I've been doing C/C++ for like 20 years and usually for the right reasons (game dev, voip, embedded, desktop apps, proxy servers). When C++ is not needed, I choose Python. I am super impressed by Rust. As of about a year ago I try to reach for it in any situation I would have otherwise reached for C++. What stands out to me more than any particular feature is how competent the Rust creators are in designing for performance. The performance of C++ almost feels like an accident, because it was designed when computers were slower, and because for awhile it was the only game in town (even sloppy C++ often performs better than high-level languages). With Rust, performance is an ethos. It is very apparent from the language design and standard library design, that these people know what they are doing.
- oconnor663 5y agoHere's one of my go-to examples. This is spawning 10 threads, each of which appends some characters to a shared string. First the C++ version: shared_ptr<pair<mutex, string>> my_pair = make_shared<pair<mutex, string>>(); vector<thread> thread_handles; for (int i = 0; i < 10; i++) { thread thread_handle([=] { lock_guard<mutex> guard(my_pair->first); my_pair->second += "some characters"; }); thread_handles.push_back(std::move(thread_handle)); } for (auto &thread_handle : thread_handles) { thread_handle.join(); } And now the exact same code in Rust: let my_string: Arc<Mutex<String>> = Arc::new(Mutex::new(String::new())); let mut thread_handles = Vec::new(); for _ in 0..10 { let arc_clone = my_string.clone(); let thread_handle = thread::spawn(move || { let mut guard: MutexGuard<String> = arc_clone.lock().unwrap(); guard.push_str("some characters"); }); thread_handles.push(thread_handle); } for thread_handle in thread_handles { thread_handle.join().unwrap(); } ===== Highlighting some visible differences between these two examples ===== - C++ doesn't actually need shared_ptr here. It would be happy to access a string and mutex on the caller's stack, and the only reason I didn't do it that way here was to keep the behavior as close as possible to the Rust code. However, Rust requires the reference-counted smart pointer (Arc = "atomic reference counted"), to avoid holding direct references to objects on the callers stack that might hypothetically not live long enough. Basically, Rust doesn't understand that the join loop makes it safe.* If you want to access caller stack variables from threads in Rust, there are ways to do it (see Rayon or Crossbeam), but the basic std::thread::spawn won't let you. - Mutex in Rust is a container of one element, kind of like shared_ptr and Arc are. The MutexGuard that you get from it is also a smart pointer to the contained element. You dereference it to access the String on the inside, here implicitly with the `.` operator. This is a big part of Rust's safety story: it's syntactically impossible to access the String without locking. - Because C++ copy constructors are implicit, moving `my_pair` into the closure invokes its copy constructor and bumps its reference count. But the equivalent syntax in Rust does a bitwise move, which doesn't run any type-specific code. So to get the effect of a type-specific copy constructor in Rust we use the explicit `.clone()` method, which bumps the reference count of our Arc. (If we had forgotten this and tried to move the original, it would be a compiler error, because Rust moves are destructive, and the compiler knows the for-loop will move more than once.) ===== My thoughts about this ===== - This Rust code is genuinely difficult for beginners to write, no doubt about it. You really have to familiarize yourself with all the relevant library types before you can get threading code to compile. - That said, there are so many mistakes we could make in either case, and all of them are compiler errors in Rust. For example we could forget to use a lock entirely, initialize our lock guard inappropriatey, or accidentally take a shared/read lock when we meant to take a unique/write lock. Or perhaps(*), we might throw/panic before completing all the joins. Those mistakes will compile in C++ and fail TSan (or abort) at runtime, but they won't compile in Rust. - I think the scariest mistake here might be accidentally keeping a pointer to the shared string past the point where you unlock. For example, maybe we pass the string to some method that implicitly takes a string_view of it, and stashes that view for later. Rust catches this too! It knows that references to the string borrow the MutexGuard, and it will not let them live past the point where the MutexGuard is destructed. - I think it's interesting to ask why Mutex isn't a container in other languages. (Or at least, in other languages that support generic containers.) I think the previous bullet is the answer. It's nice to get a syntactic guarantee that you've locked the Mutex before you touch its contents, but when there's nothing stopping you from keeping a reference too long, you can't actually make the strong guarantees that you want to at compile time.
- neilv 5y agoI used to write a lot of C and C++ professionally, and have long thought that C is 100 times harder than is suggested by the apparent care taken writing much of the C code we've seen. I've also done a lot of professional Lisp, since you asked. :) I've only done a tiny bit of Rust thus far, and am not yet ready to say it's the holy grail of systems-y software development. But Rust has enough good and interesting ideas, and what now looks like a good community process for its evolution, and I've seen enough examples of people doing good work using Rust-- that I can imagine Rust turning out very well, and I'm willing to invest, and find out. (Ideally, at some point getting paid to do so, rather than with a slow trickle of weekend projects.) I'll acknowledge a potential conflict of interest here. Compared to C, the difficulty of Rust seems much more immediate, and harder to fake, or to naively blow past. When you have to think and learn a lot just to get nontrivial code to compile, that seems like a higher barrier to entry for new practitioners. Which means, besides the usual tech industry dynamic of always getting new keywords on one's resume, and boosting the keywords that differentiate oneself... there's the aspect of Rust simply having a better competitive moat than, say, is had by yet another slightly different Web framework. That's not an attraction for me, I don't think, but it's difficult not to realize, when we're surrounded by that dynamic. I think there are better reasons to be interested in Rust, but I'll try to look out for, and be honest with myself about, potential conflicts of interest along the way.
- deleted 5y ago[deleted]