Yeah...
On my last C++ project, one very productive co-worker kept disabling -Wall, etc., because "nobody has got time for that." I periodically fired up valgrind and chased down assorted memory issues.
So, yeah...
As a im a (mostly) C++ programmer, despite the fact that i liked the language, i feel that the balance between what the language was giving me, and the productivity, was not worth it when compared to C++.
I feel much more productive in C++, the language is still faster, with a low memory footprint in the majority of cases, and with modern C++, smart pointers, move, a correct understanding of the ownership model .. the bad sides of it, the ones Rust did a better job shelving us from, from my point of view are not worth paying for the lack of productivity i felt in Rust as compared to C++.
I know this is an unpopular opinion here in HN, but I decided to take a different approach .. instead of "one language to rule them all" i tend to use C++ for what's good at, and Swift for more application centered goals , because its nicer than C++ and Rust (in my opinion), release you from the burden of managing memory all around while being very fast at the same time.
Swift for me is "the better Java" we were looking for, Rust does not seem appealing in this arena (and the same goes for C++ here), while you pay for what you use in Rust in terms of productivity, even compared to C++.
The other thing that makes C++ a better option in my opinion, is the ammount of libraries and codebase you have access to, not only in C++, but in C. Very important codebases are either C or C++, even the newer ones like Tensorflow or V8, Chrome, LLVM, etc ...
I understand the importance of what Rust provides, I like its goal, but your comment sounded like the OP was either stupid or lazy / incompetent by using your anedoctical evidence. (While in the same anedoctical example you are the hidden figure who are sensitive about security while still using C++, as the 'lazy guy', enabling -Wall, using Valgrind, etc)
When I entered in the comments section here, I was just expecting the sort of comments in the spirit of "how could you even do that?"
PS: Im not the kind of guy who tends to disable -Wall -Werror to have more productivity and i would not favor C ++ in exchange for Rust, if i feel the balance were better among what i pay in terms of productivity were fair in exchange for more safety as compared to what I have now with C++.
I know this comes at the cost of performance when compared to Rust when compared to memory management, but the value proposition in terms of productivity is huge. And recently I've done some experimentation with optimizing Swift for performance, and Swift can actually do surprisingly well there too if you stick to certain patters.
I think Rust has its place, and for things like kernel development, firmware, or software for a mars rover where you absolutely want the strongest compile-time checking of your code with respect to safety with a minimal cost to performance, it is a natural choice. I'm not convinced it's categorically better for all use-cases.
Java and .NET platforms, with C++ only when really required.
So for me, and the people I work with, whatever alternative comes to replace C++, needs to fit into the same workflow and IDE mixed language development tooling that others are already comfortable using.
And I do advocate both ways, managed languages getting features that reduce the need to reach for C++, safer C++ replacements that might eventually succeed long term (C++ took 25 years to reach where it is now), and exactly because C++, or even C, isn't going away tomorrow, ways to improve existing code quality.
Because the ultimate goal is to improve our IT stack, and not celebrate yet another Morris Worm birthday.
C++ excels at interop. As you mentioned there’re many libraries that only support of C or C++ but for me their set is different, most often I need to consume native OS APIs and GPU APIs. Also, C++ is good at number crunching, when performance matters, e.g. because first party SIMD intrinsics support.
For everything else I use C#.
Until, you natively start thinking and writing code with idioms that the borrow checker is tuned for, there will be friction.
> Although the first edition of K&R described most of the rules that brought C's type structure to its present form, many programs written in the older, more relaxed style persisted, and so did compilers that tolerated it. To encourage people to pay more attention to the official language rules, to detect legal but suspicious constructions, and to help find interface mismatches undetectable with simple mechanisms for separate compilation, Steve Johnson adapted his pcc compiler to produce lint [Johnson 79b], which scanned a set of files and remarked on dubious constructions.
-- https://www.bell-labs.com/usr/dmr/www/chist.html
C static analysis tools, being ignored since 1979, because "nobody has got time for that."
domain specific knowledge (e.g. 3d math, usability)
correct program writing
And you do them in sequence rather than in parallel (and then of course your boss declares phase 2 doesn't get any of your time).Lots of software engineers really emphasize the second part. But this is like insisting on correct shoelace tying in a shoe factory ... it's nice, but without making a shoe in the first place there is no shoe and no need for shoelaces. And when it comes to choosing between no shoe or badly tied shoelaces ... the choice is clear.
This is why the neverending complaint of software engineers that no-one cares about correctness. Entirely true. You can do without correctness (if there's anything Microsoft taught us), but you cannot do without domain knowledge.
And it's a bit self-serving: guess which one is most often missing in software engineers ?
Even for exploratory code. Unless it's such a performance critical portion of the project that I'm willing to write it in a different language for speed, why bait myself so?
If one of my goals for a project is to write somewhat functionally, I wouldn't start off with an exploratory approach using procedural techniques. I think we can all see what I'd probably end up with in the end, and it might work, but it probably wouldn't have some of the attributes I was hoping for.
There is a lot of C infrastructure, almost anything can work with C too...
He-he
You'll notice the top rated comment, & majority of comments, agrees with their decision to switch to C++. Yet we'll persist that Rust is an elitist community..
Having read those comments, many of them can be best characterized as politely dismissive, e.g. from the top rated comment "If the author is more comfortable writing this code in C++ it makes sense to use it, but I feel like there is a long way to go to make this code "safe" regardless of language. " , elsewhere "I get that this project probably values developer efficiency over safety or correctness, and probably makes sense in this use case.", etc. Still smells kind of elitist to me.
The comment seems to just be saying that it’s reasonable for someone to make this trade off when they are more knowledgeable and familiar with one language rather than another.
I think your reading quite a bit into that comment to take it as elitist.
I strongly disagree with the Rust mentality, and the general mentality of statically typed languages with extremely prohibitive compile time checks, that seem to become more common.
Underlying that model seems to be a concept of software like a sort of renaissance master's marble statue, error free and perfect at time of production.
The downside that the author points out seem to be often neglected. Constant interruption and battling with the type system during development, when mental overhead is a problem. Coupling components by types propagating through software, increasing time and effort to make changes to your software, increasing the overhead for others to contribute.
In my opinion the dominant metric to evaluate the usefulness of a language's type system should be its overall effect on cost, time spent, productivity, ease of development and capacity to change. Everything else is very subjective or just an aesthetic concern.
Dunno about Rust specifically, but I have written a little Haskell, and a significant amount of OCaml. I found that the type system reduces my cognitive overhead, compared to looser languages like Python or Lua. The compiler is disciplined, so I don't have to be.
In practice, with few exceptions, when the type system is refusing to compile something I just screwed up, and I'd better fix my mistake right away. I'd wager that with few exceptions, when Rust is refusing to compile something, you are making a mistake that in C++ would have bitten you down the line.
What you call "fighting the type system", I call "fixing bugs".
Taking some C++ code from an explorative phase that "usually works kinda ok" to something seaworthy requires, in my experience, a huge amount of work (which usually neglects a few issues that will bite you later regardless). I'm not so sure the (probably) faster exploration in C++ compensates for this compared to more "strict" languages like Rust.
Of course, if the functional requirement is only "usually works kinda ok", then you don't really need something like Rust.
Likewise, with Rust it is a relief after Go. In Go interfaces are a massive part of the language and they can only be pointers, which means much of your programming experience holds mental overhead needed to frequently answer "is this variable safe? Can I access it, or might it be nil?".
There's definitely overhead in learning how to use the borrow checker, but I feel that's the same as any basic language features in any language. Once learned, I largely don't think of them, and I don't fear using variables or what is concurrently safe anymore.
With a more loose way of going about things, you don't have to write the spec. Spec'ing is hard, sometimes harder than actually solving the problem.
I feel like someone is going to point out that spec'ing is a lifesaver in a certain situation, and I would agree. But perhaps not all situations.
You end up with the same spaghetti code messes, unexpected runtime errors, indecipherable crashes, etc. no matter what degree of strict verification tooling you use. The introduction of lazy evaluation, difficult to debug tail recursion implications on memory consumption, elevating IO into the type system, burying details deep in type class patterns, relying on dozens of special case compiler directives to enhance Haskell... it becomes the same shit code mess as any other paradigm.
This assertion is just wrong. The author makes it quite clear that he doesn't know the language and is still taking his first steps ( "I am still a Rust learner, not a veteran" ), he implies that has problems with correct memory management and best practices while using other languages (core dumps heart attacks), and claims that one of the most important aspects of Rust is that "it's memory safe".
Of course, memory safety is achieved through compiler checks.
However, the author is still someone who does not know how to use a programming language and is still bound to not only the mental model of another programming language but also bad practices that lead to problems. If someone tries to write broken C or C++ using Rust and Rust's compiler starts to throw error messages pointing out the errors the programmer is making by trying to write broken C or C++ in Rust then obviously Rust is not the problem. It is im fact the solution, and a solution that's being ignored.
Heck, the author praises Rust and it's memory safety, but then proceeds to criticise Rust's compiler because, as he puts it, the compiler will stop you from doing unsafe stuff again and again. Isn't that the whole point? Or is anyone expecting that your memory corruption problems will magically cease because you write your same old memory allocation and access bugs in Rust instead of C or C++?
Well, that's the same attitude ("the language is fine, you just don't know how to use it, that's why you have bugs") that led us to 30+ years of shitty unsafe C code.
Now it's applied to the other side (Rust is fine, you're just not good enough in it yet to use it properly, that's why you're discouraged).
Well, sometimes the language is not fine, and its ergonomics can be all wrong.
In C it was the type looseness, bad standard library, and presence of many foot guns.
In Rust it's the overt explicitness of the borrow checker, and the friction it adds to one's programming.
I don't care if the author is a Rust expert or total newb. Someone who can write a 3D modeler in C++ is someone who should be able to use any new Algol-derived language with ease in short time, regardless if they hasn't seen a line of code in that language before.
If they can't, something's wrong with your language's ergonomics.
I think the biggest problem with advanced type systems and complex compiler checks is that they are only desirable when you know the code you're writing is the the right one. A lot of the time, you're exploring a solution and don't care about edge cases, since you're not sure you've even found the right happy path. At this stage, you don't really care if your code is handling all required inputs, if it doesn't have leaks etc. - you just want to run it and see whether it at least sometimes produces the right output. At this stage, you're often fighting the compiler.
Once you know that you're on a good path, then you start caring about safety and all the other bits, and the compiler starts becoming a trusted friend.
It would be really interesting to have a system that supported both modes, e.g. starting from Rust but setting a flag to turn borrow checker errors into warnings or something similar. I'd bet that would change many people's perspectives, like the author of this article.
If they can't use the language, the Rust community should perhaps listen to them. Or should have listened to them 10 years ago, because let's be frank: the friction is coming from the fact that Rust can't be changed any more so that it becomes as ergonomic as other languages people are used to. It's also moved heavily in the direction of some FP concepts which have zero overlap with C and arguably little to do with C++.
The big assumption Rust is based on is that people will recognise the benefits of memory safety and be willing to pay the price for it. Many outside the early adopter group won't be, that's how the mainstream works.
Rust ensures that all valid rust programs are safe, but this does not mean that programs that are difficult to express in rust are unsafe.
Consider how future improvements to rust may make some previously difficult to express patterns easier. I think non-lexical lifetimes would be one such example. You could imagine that someone who learned on a future version of rust might be similarly annoyed at compiler errors when working with an old version of rust that's more limited in what things can be expressed and understood as safe.
If the coder's C++, that is written in flow without being distracted by borrow-checkers and whatnot, is in fact correct code, then no, there is no solution that is being ignored; what's being ignored is a "problem in search of a solution".
> Or is anyone expecting that your memory corruption problems will magically cease because you write your same old memory allocation and access bugs in Rust instead of C or C++?
That's a pretty good executive summary of the Rust cheerleading.
In fact, what you describe is sometimes possible. For illustration, let's confine our attention to use-after-free bugs and memory leaks. If we make the free function do nothing, and stick in a garbage collector, then in fact you can write (some of) "your same old memory allocation and access bugs" yet they are mitigated.
Types serve as explicit documentation for facts about the system that would otherwise have to be reconstructed by every reader. Type checking ensures that any change to one part of a system still interfaces consistently with all the other parts.
Writing in a dynamic language can be faster, since you can skip writing down information that you would have to be explicit about in a static language, but once that information has been purged from your mental cache, IMO that's when the system acquires the immutability of marble.
(The other nice thing about dynamic languages is certain patterns are often syntactically much cleaner.)
But once I got the hang of it progtamming Python became less and less attractive. The most interesting thing about rust is, how fast you can get up to speed with understanding what somebody elses code does.
The thing however is: if you try to write Rust like Python or C, you’re not in for a good time. It took me 3 months to stop using ingrained OOP patterns I really thought I needed because this was the way how I did things back in Python.
The moment I started to become interested into how to structure code in Rust, was the moment it made click for me. Seems it is much easier to program WITH the compiler than against it — who would have known!
It makes sense for developers to want development to be easier and for businesses to want it to be faster but it feels lazy and cheap to actively avoid tools that would help us produce better programs with much stronger guarantees in the name of ease of development.
It's not like rust's checks are arbitrary. If you wanted Rust's safety and guarantees in C++, then you would still have to do all the things the rust compiler is doing for you.
How course it's hard for them right now.
Guess what, it was harder when they started c/c++ decades ago. There was less tooling, best practices were even less clear, all code bases looked different and the language ergonomics were way worse than today.
Give it some time. Some time for the language to mature of course. But more than that, some time for the dev to actually reach fluency, not only it the language and ecosystem, but on the general philosophy of this way of producing software. It's even harder given many have to unlearn years of experience and patterns that made them productive, and adopt, discover, or even even new ones to replace them.
We have hugely high expectations towards rust because of the amazing work the core team has already made in so little time.
I see the same reaction toward the last 2 flight crashes. People are shocked this can happen. I'm just amazed it doesn't happen more often. The institutions have generally done a fantastic job.
Now to say we should not fix what's broken in both cases.
But let's be fair to the incredible result we already got.
The author was doing unsafe stuff and the compiler complaining. Once he gets in the swing of things, doing it right will become his natural flow. Verbosity of a language is a valid complaint that never goes away no matter how idiomatic your code writing gets but as written I'm not sure this was the author's complaint.
Of course the problem is: would people just add the flag to their configuration and never disable it? I think they would not. Because people mostly use defaults. That's why instead of -Wall -Wextra -pedantic with possible -Wereor for development, most places I worked in ignore most default warnings and just occasionally run some kind of static analysis. Even though many times the analysis often results with things that would be detected with additional warning flags.
And yeah I hate it and I wish that warnings would mostly be treated as errors or silenced when applicable. Then there are always separate efforts to "clean the warnings". But afterwards new code just introduces new warnings, because people are trained to ignore them.
I assume that Rust developers don't want my scenario to happen at all, but I feel that with defaults reversed it wouldn't.
But maybe it's to great a risk? Of course as always it's a game of trade offs.
There's a plan to use https://github.com/CraneStation/cranelift for debug builds instead of LLVM, which would make them faster at the cost of supporting fewer targets, and producing worse code.
I think this is more post-hoc justification than anything else. There seem to be an awful lot of developers concerned about memory safety since rust started becoming trendy and I don't think many of them were coding in ada before rust existed.
>Underlying that model seems to be a concept of software like a sort of renaissance master's marble statue, error free and perfect at time of production.
Most of the time I'm writing code isn't for the first implementation of a green-field feature and, really, most programming problems aren't that hard in terms of logic flow. If I refactor and the type system and static checking don't complain, I can be reasonably sure it's going to work. And I've seen too many 'temporary hacks' that became forgotten and leaked to review or production.
> In my opinion the dominant metric to evaluate the usefulness of a language's type system should be its overall effect on cost, time spent, productivity, ease of development and capacity to change. Everything else is very subjective or just an aesthetic concern.
I agree with your overall dominant metric. But I come to a different conclusion of what language/libraries bring me there.
To me a type safe language, is a refuge, a comfort zone -- away from the wilderness, unpredictableness and punishing complexity of troubleshooting -- associated with untyped languages.
Good luck making changes to a 100kloc Python codebase.
You can't disassociate dynamically typed languages from (strong) test suites, so one needs to qualify:
> Good luck making changes to a 100kloc Python codebase without test suite
versus
> Good luck making changes to a 100kloc Python codebase with a good test suite
In context, the first case is no different from "Good lucking making changes to a 100kloc Rust spaghetti-coded codebase", and one can't meaningfully judge a something based on a poor use of it.
The cost is requiring a developer with stronger cognitive abstracting skills. Those people tend to be academics (its almost a definition of a good academic) and also, perhaps, less pragmatic.
The ease of programming is not merely a matter of knowledge or experience, base cognitive skills play a very significant part which are largely an at-birth and developmental factor (cf. The Neuroscience of Intelligence (Cambridge Fundamentals of Neuroscience in Psychology)).
Probably languages requiring a proficiency at dealing with highly abstract relationships as part of the activity of programming are never going to be mainstream. Most people find that too difficult to do easily, and so too tasking to program.
That isn't the general case however. Some people find it easy enough, and so do not see this tradeoff. For these people, the clear benefits in creating a statically "correct" program outweigh the minor difficulty in creating it.
For the able, this "difficulty" is perceived as fun, and as frustrating by those who aren't. When something is beyond our basic capacity we tend to see it as "needlessly difficult" and not worthy of our time/attention (and of course, for us, it is).
In otherwords: the unable are often snobs.
eg. "Acting is stupid", "Rust is crap", "Painting is pointless" etc. -- all amount to, "i struggle to do that".
I'm not sure I agree. Most type languages as implemented in common programming languages are bad at describing abstraction. This means that if you're programming in one of these languages, you are forced to reduce your level of abstraction (which is sometimes touted as an advantage).
And just because someone's smart enough to find working out how to satisfy the type checker an enjoyable challenge, doesn't mean they're dumb enough to think that just because it's fun it is always a good use of their time.
If you want to build the best company, you might not care so much about these.
But then, not all of us are running businesses. And building your company on top of the best code isn't even a bad idea.
Rust initially has been a lot about fighting the borrow checker, but once you get the hang of it it happens quite often that you write pages of a complex functionality including tests – you hit build and it just works.
I am certain that Rust prevents entire classes of problems I filed bug reports for, even with extremely experienced developers. I understand that the nagging voice of the compiler or cargo clippy is not just for everyone, tho.
The important part is to realize _why_ you’re fighting the compiler as it’s trying to make _you_ write better code and improve.
If you find non issues being reported by the compiler please report it and make it better for all of us too!
There is often a debate in the D community how the defaults could have been better: pure, @safe, const by default, no GC by default etc.
But not every bit of code need to be perfect. Code must prove its usefulness first and foremost, before the need to be reliable, safe, fast and beautiful even enter the picture.
I'd go as far as to say, thinking of a nascent project as something perfect and beautiful likely leads to over-idealization and will delay the time to completion many-folds.
Ability to write ugly code is - for me - a feature.
That said, for getting code written fast, Rust for me has been better than C++ for a while now, even though for most of that I was better at C++ than Rust. The reason for this was largely Cargo, which eliminates the pain points of dependency and build management that plague C++.
1. You still have to fight with borrow checking in Rust as in C++, it’s just not automated. You have to consider moves and copies, borrowed references, etc. As the author points out, if you’re used to writing C or C++, it’s going to take a while before responding to the borrow checker is second nature. The point is that the borrow checker is a computer and doesn’t make mistakes the same way a human does, and that’s value added not detracted.
2. Having the benifit of actually having a package manager, Rust is much easier to download and use dependencies with. That said, I agree with the general premise of not using Rust if you have an immediate business need and it’s missing a core library. My issue is that it should be fairly apparent before you start a project what dependencies you need, so a rewrite back to C++ seems odd. Also, Rust is an open source ecosystem, and people using it should feel compelled to consider writing the missing pieces they need for the benifit of the community. It’s also odd to say that Rust doesn’t have what you need, it sounds like there are C libraries that already do what you want, and Rust can wrap C.
3. If something is written in C and you don’t have time to replace it, just wrap it in unsafe and make a safe interface over it. Rust is exceedingly good at interfacing with C, so any library you can use in C can potentially be used in Rust.
I see these comments and it feels so foreign to my experience. The borrow checker was second nature to me because of my C++ experience. These were things I already had to juggle mentally. On rare occasions, it complained about something that I could prove was valid but I understood why it couldn't tell. Usually, when I hit it, it is because I forgot a case and am grateful for it. I know of at least one optimization I've made that I would never have bothered with without the borrow checker. It would have been too much bother for me to reason about everything. Even if I did, it would have been even worse to maintain.
Because of my experience it was also plain sailing, while doing the tutorials and exercises from the books I bought.
Then I tried to make a GUI application in Gtk-rs and had lots of fun with event handler callbacks, which are the main reason why Relm was created.
It's not that easy. The borrow checker gives you memory safety and thread-safety. In C++, you always have to worry about memory safety, so here the ownership model and borrow checker is a pure win. However, in C++ you don't have to worry about thread safety in a single thread...there's no barrier to passing pointers around and mutating things from different places in your code. In rust, the borrowchecker disallows shared mutable state...that's a huge win if you want to parallelize your code later on, but it also means that things that are trivial in C++ take a lot of thought and effort in rust, especially if you're thinking in a C++ paradigm (as opposed to coming from a functional language).
This sounds like a great idea, but not everyone has the time and resources to port libraries from one language to another. It should be trivial to wrap C libraries, but errors do show up, and a once one day task now takes a week to iron out. If you have 4 or 5 libraries that are missing, you've now lost a month of development work that could have been spent adding new features.
Additionally, not everyone wants to maintain open source projects. There's a huge amount of responsibility that comes with being a maintainer, and the OSS community isn't always a friendly, fun place. Rachel has some great examples in her blog [1].
This is so misleading. Sure you still have to think about borrowing in C++ but in C++ you only have to convince yourself that you got it right. You don't have to convince a dumb child that barely understands variable scopes.
The benefit is of course that the dumb child is 100% reliable so if you can convince him then you are 100% sure you got it right...
But please can we stop pretending that it isn't a massive pain in the arse to convince the borrow checker that your code is ok.
Also as someone else pointed out, if you are only writing single threaded code the mutable borrowing rules are needlessly restrictive.
I like Rust but it really irks me when people pretend it is as easy as C++. It isn't. It is much harder - it's just that when you're done you have (probably) a better result.
No it's not.
"hard" is not single dimensional.
"hard" to write your first hello world? No, both are easy.
"harder" to write your first moderately-sized program that basically works? Yes, for almost everyone. You'll fight the borrow checker. The learning curve is real.
"harder" to write your first large/medium, correct program? Definitely not. The safety will save you, here. It's not just memory. It's no nulls, it's no exceptions, pattern matching exhaustion enforcement, baton-passing session type patterns, race-freedom, and so on. The "it compiles, it works" dynamic is akin to OCaml/SML, if you've used those at all. Except it's even better because you get prompt resource finalization.
"harder" to write your nth program after ~6 months of usage? Not by a long shot. Rust is actually an incredibly expressive language. Once you learn to shape code the way the language expects, you'd be shocked at how productive you are. It's in the same ballpark as go, perhaps a little better if you're doing something nontrivial due to the power of generic libraries.
I spend almost no time "fighting" the borrow checker, as do most ramped-up Rust programmers. It's pretty much all win at this point. It's a different category of language than C(++). It actually gets a little exhausting hearing people talk about how hard the borrow checker when folks have barely used the language.
These days, the only time I'll use a GC is if I'm writing something _very_ fast and short in Python. An experiment, a prototype, or a tool. A short REPL session. I really do not miss GCs otherwise.
But yes, compile times are somewhat slow. If you go template crazy in C++, you'll be in the same ballpark. But the "equivalent" C codebase will smoke it.
While anyone is obviously free to use any language he or she likes the whole article comes across to me as someone arguing why they dont want / need seatbelts: "They constrain my movement, I'm a good driver, etc.".
These are also the same kind of arguments one could make for wanting to use a weakly typed language instead of a strongly typed language.
Personally I like my types strong and my memory safe...
In other words, C++ is utterly entrenched in that space like Fortran is for HPC.
When a game seems to be written exclusively in a high level language like C# then there is almost always a massive framework underneath that integrates a lot of shiny C and C++ libraries for the real heavy lifting.
Modern C++ is "good enough" where you'll potentially end up with some unsafe code but unless you're writing an SSL library it'll be OK.
This is very much true while learning, and very much not true once you finished learning. It would be very concerning indeed if it were otherwise. As is, it is very concerning for Rust adoption, as this post evidences.
EDIT> I would rather have better CASE tools / an AI pair-programmer than be straitjacketed into a top-down correct-first then code way of working.
Hello. :-) I started writing C++ around 1992, and was lead programmer on various C++ production systems from 2002 until 2011. I worked with valgrind, unit tests, and boost/std::tr1 C++, but not C++14 or 17.
For the past three years, I've been writing production systems in Rust. Here are some things I've observed:
- If your C++ code relies heavily on complicated webs of objects that all mutate each other (as found in many game and GUI designs), you'll have a bad time translating that code to Rust. If your C++ code tends to be more functional, idempotent, or transaction-based, and if it has clear ownership of objects, then translating to Rust will be much easier. For example, Rust seems to work better with ECS-based games and React-like GUIs.
- Rust is significantly weaker than C++ for designs which use integer template parameters (e.g., "vec<3>") or partial template specialization.
- Modern C++ allows you get ownership 99% correct, if you throw enough tools at it. Rust gets ownership 100% correct by default. If you're dealing with situations where that 1% matters (complex threading, or decoding hostile data), then it's a much bigger difference than you might think.
- Not counting Rust IDEs (which are only borderline OK by static language standards), Rust tooling is great. Dependency management is solid, linting is good, automatic formatting is good, etc.
- I've been working with nightly and experimental builds of Rust async code, and I think that Rust will soon give C++ a real run for its money in this space. Multithreaded async executors (where you mix "green" threads with OS threads) rely very heavily on precise tracking of who's allowed to mutate what, which Rust is excellent at.
> Finally, if a Rust veteran could let me know: how does Rust deal with general resource management in the presence of exceptions?
Rust does not have exceptions. Instead, it uses `Result<T,E>` and the `?` operator to propagate errors. Ownership and RAII are 100% idiomatic and fully checked by the same systems as memory management.
That's exactly the kind of c++ code you probably don't have to refactor/move to another language at all
Re: general resource management. It works exactly the same. Rust also does RAII. Rust also doesn't use exceptions for error handling.
One easy to state advantage of Rust over C++ is that it checks your threading design.
If you want to handle closing a socket, it’s as easy as implementing the Drop trait on your type. Without an unsafe block there’s no way your destructor won’t be called.
struct Socket(u16);
impl Drop for Socket {...}
To answer your question there’s no special casing around memory vs non-memory resources. Your socket is backed by a kernel ID which must exist in memory, of course, so by adding a Drop implementation you can then define the special treatment yourself. If threading considerations exist you can explore the Sync and Send marker traits too.
It’s largely a much simpler language than C++, you just have to learn how to write it. A lot of the friction/confusion IMO is that it looks so similar to languages you use at first glance you just start writing the code you used to in a Rust-y way, instead of Rust, then are frustrated as to why it won’t build.
In some ways it’d be clearer if it looked “foreign” like prolog — it’d be a lot less popular though haha.
Unfortunately, this is not correct. Resource "leaks", involving failure to drop a resource which is no longer in use, are possible in Rust, and the borrow-checker won't protect against them. They're most likely very rare in idiomatic Rust (the case I know about has to do with RC-cycles) but they're possible.
I suspect that mesh generation is very much a mutable algorithm domain and probably a high impedance mismatch with Rust.
For example, simple things like mapping a struct of three elements to a vector of three elements were, at one point, very difficult if not impossible in Rust.
Rust forces users pay certain kinds of debt upfront that makes Rust attractive for rewriting, but I don't think it's that much attractive for greenfield projects. You'd want to fight your problems, not your problems plus Rust. On top of my head right now I couldn't think of any famous Rust projects which aren't a rewrite.
Personally I don't think Rust is that hard to learn and some of my side projects are being written in Rust. But if I ever had a business with Rust as a main language, I'd be worry I could find enough Rust programmers. Fortunately the community is addressing its ergonomics and hopefully one day its approachability and learning curve will also gain more attention.
Wut? Piston, actix, Amazon Firecracker, Alacritty, Xi, the list goes on.
Kidding. Stop fighting, people. You're all on the same team.
Everyone can do statistical problem solving. At least everyone who can talk. What you do is that you start making sounds when you're an infant and then you receive positive or negative feedback. This continues until suddenly you know how to talk.
Similarly, in industrial chicken raising you need to differentiate between male and female chicks right after they're born. However, there isn't any guide to determine the difference. Instead what you do is that you take one person who knows how to do it and pair them with someone who doesn't know how to do it. The person who doesn't know how to do it will guess at the sex of the chick and they will be corrected by the person who does know how to do it. After enough time you have two people who know how to do it.
Sounding familiar yet?
Most people learn programming languages in a statistical fashion. They try a bunch of stuff and get positive or negative results (compile fails, runtime errors, etc). However, just like determining whether a chick is a male or female in the chicken raising industry, nobody can really give you the specification of how to program. All they can do is tell you that you are doing it wrong or doing it right for any given scenario.
Now of course there are problems with the statistical method (also benefits, but we're interested in failure right now). 1) You can't say why you're right [in order to do that you have to sit down an analyze what you've been doing in a structural fashion]. 2) The only teaching method you know involves telling people they're wrong when your gut tells you they're wrong. 3) You'll have a terrible intuition for any situation that only causes a failure after a period of time or some of the time (think undefined behavior in C).
If you have only learned programming statistically and haven't sat down and reflected on what the structure of what you're doing actually is, then when you are faced with information that is contrary to what you know your natural reaction is going to be to listen to your gut (even if your gut is wrong) and provide the same negative response that you got when you were first learning.
Additionally, the only "reasons" that you'll be able to give are paper thin metaphors and thought terminating cliches that don't stand up to even the smallest amount of examination.
The end result? You get a bunch of programmers that freak out every time a new language comes out.
I would rather work on interesting projects than use interesting tools for not-so-interesting projects. So far, for things I am interested in, C++ seems to be the tool of choice.
We had such a huge push last year for ergonomics that there's a segment of the community that's still upset about it. We're very interested in improving them; if you have good ideas about it, you'll get heard out.
To be honest, this article seems somewhat ingenuous. The author wasn't comfortable with Rust, and it seems like he missed the point of the borrow checker. This article will now be circulated whenever Rust is discussed.
Here is a good article that arrives at the opposite conclusion: https://kyren.github.io/2018/09/14/rustconf-talk.html
I've been writing Rust full time for the last month and a half or so and the language is a joy to use. The main difference is that the code I write feels very sturdy and permanent. I've heard other people say the same thing.
I have been studying rust for embedded since January and I am not really impressed by what I have seen. I am mostly hacking around the deficiencies of the libraries, the crazy organisation of the stack, and the issues with the community.
I am sticking with rust for now because I feel like there is a bandwagon and there might eventually be money in it, but I am certainly not a convert.
This argument could be applied to anything.
What's crazy about Rust stack organization? What are the issues with the community?
You forgot to tell Microsoft (biggest software seller on earth)and they decided to use it in actix