Hacker News new | ask | show | jobs
by distcs 941 days ago
I've done some C++ but no Rust. I'd like to learn a few things from people who have done both.

1. How many years of C++ programming do you have under your belt? How many years of Rust?

2. For new work projects, do you choose C++ or Rust? Why?

3. For new hobby projects, do you choose C++ or Rust? Why?

4. Is there something about C++ that you wish Rust had?

5. Is there something nice about Rust (apart from the borrow checker) that you wish C++ had?

6 comments

1. About 15 years of experience in C++, 2-3 years in Rust.

2. I'm retired now, but I would have considered Rust for any greenfield project that didn't have a compelling reason to pick C++ (e.g. mandatory interop with an existing big C++ library).

3. Rust nearly every time. I sometimes use a layer of C++ as an FFI shim, such as when writing a gRPC client/server (the Rust libs there aren't mature).

4. The library ecosystem. Rust's crates.io seems full, but if you scratch the surface it's just a bunch of half-baked hobby projects at v0.x versions. And Cargo (the most popular build system for Rust) has essentially no support for multi-library packages, so instead of something like GLib (a single dep with lots of functionality) it's common to see even trivial programs depending on dozens or hundreds of half-baked hobby projects at v0.x versions.

5. Most of the Haskell/ML-ish functionality, such as traits and proper enums. I'm currently in the middle of a Rust project that's gotten much bigger than I expected (parsers are hard! compilers are hard! zero-copy is hard!), but it's still possible to make progress by leaning heavily on the type system.

I often describe Rust as "a dialect of C++ where the compiler forces Google Standard C++ on the world", or alternatively "the language you'd get if you hired a team of Haskell developers to write firmware".

Your thoughts about crates.io mirrors mine exactly. I'm becoming more and more interested in just ditching it entirely and using vendored checked-in (or submoduled) dependencies and managing the transitive dependency tree myself. Cargo&crates.io seems to have been inspired too much by npm. Lots of half-baked, abandoned libs that wantonly pull-in piles of other 3rd party deps and create a sprawling graph of dependencies that ends up with binary bloat and multiple versions of the same package, etc. etc.
FWIW, that's what Mozilla is doing.
I suspect Google is, too (Bazel).

If CLion/RustRover support was there, I'd probably switch my personal project over to Bazel+vendored deps.

somewhat OT, but what happened to haskell? a few years ago it was all over HN - now you hardly see any mention of it. surely this won't happen to rust?
Entirely different snack bracket. Haskell is great stuff, but not something you'll be able to practically staff a team and build with.

Rust is not nearly so "brainy." It's a much more pragmatic and conservative language.

And it's targeted in an entirely different domain -- systems programming. Haskell is a garbage collected pure functional programming language. Rust is not anything like that.

  > And it's targeted in an entirely different domain -- systems programming.
  > Haskell is a garbage collected pure functional programming language.
At the time there were many people trying to make a go of doing systems programming in Haskell. I remember lots of arguments about libraries using ByteString/Text vs String in their public APIs, where the research people were like "linked list of u32 is so conceptually pure!" and the systems people were like "what, no".

You can see the Haskell influence in Rust today, for example the popular benchmarking library <https://crates.io/crates/criterion> is directly inspired by <https://hackage.haskell.org/package/criterion>. I've seen a lot of the same names in the Git logs and chat rooms.

In retrospect, starting with a low-level systems language and adding safety turned out to be a better idea than using `ST a` to implement borrow-checking in a high-level GC'd hosted language. I can only say "it seemed like a good idea at the time...".

Purely my opinion:

There was an era of stability in the Haskell project during which it was possible to write code for industrial purposes. A lot of people were attracted to the idea of a memory-safe language that compiled to native binaries, and there wasn't much competition in that area at the time.

Then the research-oriented nature of the language and community re-asserted itself with Haskell 2010, and there was a lot of churn in both the base libraries and Hackage. Around this time was when Swift, Go, and Rust had their first releases, all of which offered memory safety and varying levels of ML/Haskell inspiration. So Haskell was suddenly less appealing, and there were other options -- why file another perf-regression GHC ticket into the void when Go has an HTTP server built right into the stdlib?

I don't think it's got anything to do with Haskell 2010. Haskell is far more widely used in industry today than in 2010 by at least an order of magnitude. Heck, Mercury alone has about 250 Haskell programmers I think. That's probably more industry Haskell programmers than there were at all in 2010.
As far as I remember, most of the pillars of Haskell were hired to work on projects that were, at some level, competing with Haskell (by Microsoft, Facebook, Epic).
> 1. How many years of C++ programming do you have under your belt? How many years of Rust?

12-15 years of C++, 8 years of Rust. I generally used C++ because it was the only tool that could do the job at the time, not because I actually liked it. At best, I had a love/hate relationship with C++.

> 2. For new work projects, do you choose C++ or Rust? Why?

Almost always Rust. The main reasons:

- Cargo is awesome, and the crate ecosystem is incredible.

- I barely trust myself to write rigorously correct C++, despite having plenty of C++ experience and being extremely paranoid about code correctness. And I defintely don't trust most other people to do it correctly. (I have maintained more than my fair share of other people's C++ code, and the average C++ code is buggy garbage.) C++ is like fishing around in a drawer of extremely sharp knives in a dark kitchen; you're going to get cut.

- I trust the average Python or TypeScript developer either to write correct Rust, or to be defeated by the borrow checker. This isn't just the borrow checker—it's also bounds checking on arrays and slices, the choice to panic instead of corrupting memory, the rareness of undefined behavior (and "nasal demons", and irresponsibly aggressive optimizations) in safe Rust, the safe mulithreading support, etc.

However, I would consider using C++ in domains where correctness and security weren't important, and where I wanted to use mature frameworks. Games would be an obvious case!

> 3. For new hobby projects, do you choose C++ or Rust? Why?

Rust. Way more fun, personally. :-) I tend to like using "functional" architectures, so I don't fight the borrow checker much.

> 4. Is there something about C++ that you wish Rust had?

Well, now that const generics are in, I'm pretty happy with Rust's feature set. But for quite a while that was the best C++ feature Rust was missing.

I currently work in a mixed C++ & Rust shop -- embedded Linux, autonomy systems for tractors -- and know C++ very well. I choose to work exclusively in Rust.

1. 10-20 years of C++ depending on your definition. But used C++ part-time casually/open-source from mid-90s to 2012 or so, and then mostly full-time from that point on @ Google, with a big chunk of that working in the Chromium source tree.

2ish years Rust, including the last year or so fulltime professionally.

2. Rust. Because of the more expressive type system, simplified/cleaner tooling, consistent syntax and style. The safety features are nice, too. C++ projects at work tend to get wrapped in Rust for the project I work on.

3. Rust. Same reasons as above.

4. C++'s const generics and constexpr support is much richer and better than Rust's. Placement new and custom allocator support in the STL has no answer in Rust yet, and the efforts to fix that (allocator_api etc) seem terminally stalled. Same with really good cross platform simd library support. C++ has a better story generally on embedded devices still, in terms of sheer # of toolchains.

5. I am not sure why people are focused on the borrow checker and safety as somehow the only distinguishing feature -- it's really not. C++ is missing a whole boatload of things from Rust, but most notably would be ADTs/sum types/pattern matching. This is the "secret weapon" of all languages inspired by the ML-series functional languages (StandardML, OCaml, etc.) and something C++ has no real answer for, though you can "sort of" approximate it with some template metaprogramming wanking I guess. Rust doesn't do this as well as ML or Haskell or F# or Scala because it confines it to its enums, but it's still really lovely and makes programs far more expressive and readable.

Pattern matching can be done over structs as well, in Rust.
Not nearly as expressively though. You can destructure a struct, but you can't express alternatives on anything but an enum. Languages like F#, Scala, Haskell support more ways of creating ADTs than the kind of enums that Rust has.
same here embedded Linux,until rust apps can share the same shared libraries as c++ can, we have a size issue using rust,so,no rust
1) C++: 7+ years; Rust: 3+ years.

2) C++, my employer's choice. Their rationale: easier to hire people with experience, internal codebase is mostly C++ so tooling/people more versed.

3) Rust. For me it's just easier overall to work with. It takes me an hour or so to get my head back into Rust's standard library and idioms/quirks, but afterwards it feels much better to work with: dev. workflow, testing, expressiveness. Plus it catches programming errors for me every once in a while.

4) I wish Rust had wider adoption by the industry. It's always compared to C/C++/Java/Go and the usual argument boil down to "not enough people use it".

5) I wish C++ had better compiler error messages. I have to rely on instinct when it's not scrolling through nested template/SFINAE errors to understand what's happening. Rust tells me "here's what's wrong" 99% of the time.

1. I had about 7 years of professional C++ experience, a few more as a hobbyist. By now, I have ~10 years of Rust.

2. I would definitely choose Rust. For better or for worse, the teams I work with tend to consider developer velocity as their highest metric. Between cargo, clippy, crates and the type system, I'm orders of magnitude more productive in Rust.

3. Same thing. My life is too short to spend it debugging memory or concurrency errors.

4. There are a number of C++ libraries that have no equivalent or good bindings in Rust yet. But if you're talking of the language, no. There are C++ features that do not have an equivalent in Rust but I don't miss them.

5. From the top of my head, affine types (e.g. after a `std::move`, the type system ensures that you can't use the value anymore), proper enums, proper pattern-matching, better concurrency operations in the standard library (which pretty much requires affine types), a linter as good as clippy, built-in support for writing new linters/gradual type systems, derive macros (that have access to the AST).

1. Hard to count. Started as a youth on game modding, but in terms of serious projects, probably 5-7 years.

2. Rust. It's a Rust shop, and the only C++ we have is in dependencies that we wrap with Rust interfaces.

3. Rust. I've probably shaved a not-inconsiderable amount of time off my life in debugging C++ issues at both compile-time and runtime (inscrutable behaviours, memory safety, broken / unstandardized tooling, platform-specific nonsense, template metaprogramming sins that I've had to debug and - worse - add to, and much more)

4. Hmm. Template specialisation and more constant-time evaluation, I think. There's probably a few others, but that's what comes to mind.

5. Uh. Pretty much everything?

- Consistent tooling that works across all platforms (I will be happy if I never have to look at a line of CMake ever again)

- Built-in dependency management

- A robust engineering culture (your code should account for failure!)

- Consistency of code itself, made possible through rustfmt and clippy

- Generics that surface issues at point of definition and not at point of instantiation

- ADTs

- Reduced reliance on human strictness / "getting it right" to, well, get it right. This isn't just the borrow checker - most APIs in Rust are designed to make using them wrong difficult. Even things like `Mutex<T>`, which combines a mutex and value, to make sure you can't access the value without locking, and you can't lock without knowing what you're locking.

- Easy multithreading through invariants that the compiler tracks (the Send+Sync traits); they're not perfect, but there's nothing like the first time you change an `iter` to Rayon's `par_iter` and your code is magically eight times faster.

- A value-based typed rich error handling scheme, so that you can see what errors a given piece of code might produce and be able to handle and propagate them with little fuss. (Similar to checked exceptions, but much more convenient! Adding some context to an error is a function call and `?` away, not a per-statement try-catch-rethrow).

---

Honestly, I could keep going for a while, but my general point is that Rust has had the ability to learn from its predecessors, and it shows. Many of the mistakes, bad ideas, or poorly-fitting features of past languages just aren't present in Rust because the language was deliberately designed to avoid them.

It's not a perfect language by any means - async Rust is the first and most obvious pain point - but it solves my problems in a much more ergonomic - and dare I say it, more fun - way than C++ ever did.

> ADTs

C++ is already a very complex beast as it is.

ADTs (and pattern matching) make it concise to express many different programming things.

But I'd imagine that adding it to C++ would be horrendous.

Well, they already did [0]. It's not very fun to use; something that was less miserable would probably see more use. Retrofitting them to a language isn't impossible, either; there are a few languages that have managed to do it by adapting to their ecosystem's mores, like TypeScript and Kotlin.

That beings aid, I don't disagree with your general point. C++ is already incredibly complex and impossible to understand as a single individual; I don't think that can be fixed without removing things from the language.

My gut feeling is that the future of C++ is not C++, it's cpp2 or Carbon.

[0]: https://en.cppreference.com/w/cpp/utility/variant