Whereas Rust, to me at least, is 'ML-ish with curly braces'. So, a language firmly based in the ML heritage with C-like syntax. So, fundamentally working with types and 'typeclasses' and heavily leaning towards filter/map/fold/reduce/lift/unlift type of thinking. Sure, throwing funtions around as first class objects are not as easy or straightforward as it is in 'real FP' languages, but that's a trade-off I'm willing to take for the guarantees that Rust provides.
I'm genuinely curious what's the reasoning behind being able to assert that 'Rust is a cleaned-up C++'.
SML, OCaml, C++ and Haskell are all mentionned.
- Doing Option<T> -> Option<U>
- At what point do I do Option<T> -> Result<T>
- Should I transpose Vec<Option<T>> to Option<Vec<T>> now or later?
- Often reaching for algebraic data types
- How to map over this to collect it into what I need
- Ah, it needs to implement Hash, Eq, PartialEq ... SomeTrait to make it work the way I want
- Pattern matching all over the place
All of which to me mentally feels more like something along the lines of F#, OCaml or Haskell than C++ that 'normal people write'.
When I did my degree, C++ was taught in the second year and Caml Light in the third.
That's a brilliant metaphor to drive home the safety advantages of Rust! "It's a table saw that won't chop off your fingers!"
That's a "shut up and take my money" proposition. (And it helps that it's a really good table saw too.)
(As another aside, I got to the testimonial from an employer talking about the peace of mind of knowing the workers on the shop floor are safe and it "clicked" for me: you've got metrics and liability for job site safety so you can quantify that peace of mind. We still not there with software quality liability eh?)
... and... doesn't it still work ? An awful lot of C++ applications are being written today, and that can be done at a pretty high abstraction level thanks to the type-level facilities of C++.
> . Few in the embedded space find it appealing, many of those who use C++ do (as it is certainly a cleaned-up C++, and a nice improvement in comparison), but too often not appealing enough to switch now, and some in the application space who don't know or don't remember the C++ lesson do adopt it now (sometimes out of sheer novelty) but will likely abandon it later for similar reasons C++ was largely abandoned in that space.
are we talking about the same embedded? most C shop migrate to C++. most car brands, and a lot of appliances, use Qt for their UI (C++)
C++ is nowhere near as dominant in the application space as it was in the early nineties. "An awful lot" in nominal terms for sure.
> are we talking about the same embedded?
Probably not. C++'s niche is "low-level with capable hardware." Some "embedded" software does actually run on very capable hardware.
You’re rewriting history here, friend.
Hardly anyone was writing embedded C++ in the 90s. Even nowadays I bump elbows with Developers that refuse to make the move from C in embedded.
If we’re talking Desktop apps, well... yeah, Windows was the new hotness, OOP was hot ‘n fresh, and Visual C++ was a BFD. Once more languages came about, people found ones they preferred over C++ (Java was a BFD).
As to your last comment, I’m guessing you haven’t worked in the embedded space with C++ if that is your conclusion
I wasn't talking about embedded in that section, but about applications, and not just desktop.
> Once more languages came about, people found ones they preferred over C++
High-level languages were used a lot before, like VB and other RAD languages. But the belief was that they'd be too slow for many applications, like servers.
> As to your last comment, I’m guessing you haven’t worked in the embedded space with C++ if that is your conclusion
That is correct, and yet the lower the hardware capabilities and the higher the required safety, you see more C and less C++.
what do you call "capable" ? C++ is routinely used on atmega328, a 16mhz uc with 2kb of ram.
And what decisions would that be? Your post seems self contradictory to me because it implies that Rust is both too "low abstraction" to be "extremely appealing" to C++ crowd, and too complex and "hard to analyze" to displace C in use-cases that require portability and/or are resource constrained.
If there's anything we can learn from programming languages -- be they C, C++, Ruby, PHP, Haskell, or Java -- riding the hype-train led by PL enthusiasts and early-adopters is not a good recipe for long-term success (even if it is a good recipe for long-term hype). Like with fashion (and I think HN is more like GQ or Vogue than actual industry news; i.e. it is more aspirational and inspirational than descriptive or prescriptive), the languages people talk about and those they actually use for many years are usually not the same.
That's exactly what Rust is doing. It used to have a runtime, green threads and a GC, but it doesn't because that's not what C++ developers want. And recent development work has been focussed on const generics and const fn which are both keys things seen as missing by C++ developers.
From the perspective of someone who's been writing Rust professionally for the last few years, the hockey-stick curve started kicking in in late 2020 or so.
But you can even have a rough estimate according to your own measure. There are roughly between 50K and 100K developers working at FAANG (maybe replace Netflix with Microsoft). How many of them would you guess are using Rust?
Why would you want Rust to target lowest-common-denominator developers and become new VB or php? All it needs is enough momentum to become self-sufficient, which seems to be actually happening now with Rust Foundation and news of its usage in some major companies that can set the trends for whole industry (Amazon, Google, etc.).
Rust wants not that I wants. It seems people replacing NodeJS with it.
I don't think Rust and C++ have the same level of abstraction, for example. Rust has ADTs and pattern matching, C++ only has product types and std::variant.
There's a crucial distinction between input and output types in practice. For a given input type T, Rust makes it possible to abstract over `T`, `&T`, `Cow<'a, T>`, `Arc<T>` etc, by using a trait such as `impl AsRef<T>`.
However, Rust doesn't currently have existential types, so its ability to abstract over output types is more limited. You can implement, for example, `fn foo(&self) -> impl AsRef<T> + '_`, but you can't name that type. So if you want to return an enum, you can't write
```
enum MyEnum { MyT(impl AsRef<T>), MyU(impl AsRef<U>), }
```
Instead, you have to concretize the type somehow, either by boxing things up into a trait object (often but not always possible) or by exposing the generic param:
```
enum MyEnum<RefT, RefU> where RefT: AsRef<T>, MyU: Ref<U> { MyT(RefT), MyU(RefU), }
```
This is a real problem, though one that will be solved through existential types.
> Replacing, say, a concrete type with a trait is about as much work in Rust as it is in Assembly.
I'm not sure what you mean here. I'm not aware of any assembly languages which have traits. Replacing a concrete type with a trait tends to be pretty easy in Rust because mistakes are caught at compile time.
> I'm not aware of any assembly languages which have traits. Replacing a concrete type with a trait tends to be pretty easy in Rust because mistakes are caught at compile time.
I'm not thinking in terms of language features but abstractions. The best way to see this is to think how many different implementations to a code unit I can do without making the consumer aware? That number is significantly lower for low-level languages compared to high-level languages because things that can be hidden in high-level languages, like layout, storage and lifetime, must not be in low-level ones, hence "low abstraction." Changing something in one place is more likely to require changes elsewhere. Therefore, low-level programs are more rigid, more jigsaw-like, and their evolution more difficult.
It is true that a compiler that tells you if you missed a change helps a lot, but it doesn't change the nature of the low-level language, even though it improves its ergonomics (although it's not so simple, as sometimes even correct programs are rejected) -- you still need to do all the extra work, but it doesn't take quite as long.
Additionally at least on Windows, Microsoft still believes in C++ for doing the kind of desktop applications you are talking about.
All these scenarios aren't properly covered by Rust in its current state, even the Rust/WinRT project is doing baby steps, very far away from what VC++ offers today.
Haskell doesn't promise the type of control I need. Someone i work with rewrote our main control algorithm and proved it was correct (not in Haskell ,I just fear this problem ), but it took over a minute to run, and this PID loop needs to run at 5hz and leave some processor for other tasks. My c++ isn't proven correct but we have 15 years of production with it.
Rust promises to avoid some of the things we don't like about c++ while still worming in the real world. So of course I'm interested.
Not really; Rust is very careful to avoid leaky abstractions, compared to C++. It's definitely "low level" in a foundational sense (even reminiscent of C in many ways) but the limited "high-level" features it does have are incredibly solid and highly usable.
"It's simpler than C++!". Yeah, Rust could become a bloated mess and still be simpler than C++. It's like saying that a mountain is not high because it's smaller than the Everest. It's not a good idea to use C++ as reference.
But Rust isn't complex: there aren't many features interacting in a special way with one another with a combinatorial explosion of interactions you need to know in order not to shoot yourself in the foot. (Move semantic difference between Rust and C++ are a good illustration of that).
Actually, in terms of number of different features you'll encounter when onboarding a new project, Rust is far behind JavaScript and PHP (PHP being the biggest example of how feature bloat doesn't kill a language, even if your language is targeted at inexperienced developers).
"Why I rewrote my Rust keyboard firmware in Zig: consistency, mastery, and fun" https://kevinlynagh.com/rust-zig/
In absence of good metrics for the kind of complexity we're trying to discuss I think we kind of have to rely on these sorts of first-person subjective reports from the field.
But it does need to be said, that the approach he was using with Rust was absolutely not the right tool for the job. The author should have been using traits. That's what they're for, and they definitely aren't an obscure language feature.
And that being said, the author mainly complains about features that also exist in C (macros and ifdef, and Rust's version are easier than the C one), would you call C a too complex language because it has macros and ifdef? (I actually think that C is one of the most complex programming language ever written because you need to store too much invariants in your head otherwise it's UB, but ifdef and macros aren't at stake )
- - - -
> I actually think that C is one of the most complex programming language ever written because you need to store too much invariants in your head otherwise it's UB, but ifdef and macros aren't at stake
Like I said, without metrics we're just trading subjective anecdotes.
Metrics for complexity of machines is a subject I find fascinating, ever since I read Ashby's "Introduction to Cybernetics" wherein he asks the question "How can we measure the complexity of a machine?" in the context of a formal system for describing machines (Cybernetics.)
There is also the concept of "Kolmogorov complexity" https://en.wikipedia.org/wiki/Kolmogorov_complexity
We could compare the sizes of compilers for C and Rust.
We could teach each to different randomized groups of students and see how quickly people learn to write (safe!) code in each.
Yes, this one guy made a wrong turn once. If you want to conclude from one user making a mistake that a language is complex then you're just going to conclude that programming is complex … Everyday, with every language under the sun, people make mistakes, great discovery.
I'm not blaming “the user®” here, I'm blaming the blog post writer who makes a mistake and concludes that his tool is responsible for it and that he should tell the world how bad the tool is.
> Like I said, without metrics we're just trading subjective anecdotes.
Well that sentence is pretty ironic given the previous one, nevermind.
> We could compare the sizes of compilers for C and Rust.
I wonder what conclusion you'd draw from such a comparison. That assembly is the least complex language in existence, followed by Brainfuck and Chicken?
> We could teach each to different randomized groups of students and see how quickly people learn to write (safe!) code in each.
Oh I actually like this one. For Rust, you'd need to run a study to find out, but for C the answer is trivial: Never. Nobody on earth know how to write safe C. Not even DJB, not even Theo de Raadt, or Richard Hipp, or Brad Spengler. For almost 50 years, the brightest minds of computer science have tried to write safe C code, and consistently failed. Can we conclude that this language is a little bit too complex for humans, or should we wait a few decades more?
I wish there was a C with a borrow-checker like Rust, but without everything else.
I guess the dream of a perfect low+high level language will never die.
You seem to imply that it's fundamentally impossible ?
I definitely don't get the feeling that C++ was that popular, I distintcly remember many Linus rants about it. It's just that after years of usage it carved its own niche.
However one pain point Rust does address is parallelism. If you want to use modern systems, and you're going with C++. Good luck. You're gonna need it.
As for the popularity, I think that's moot. But I do agree Rust can't be everything to everyone. One problem it will have for the forseable future, is the slow compile speed. But on the flip side, Rust has been super popular.
But it does one thing no other language does. Safe concurrency without GC. It's like a seatbelt in a car. Once you get used to it, you'll be paranoid its not there.
----
Where I do agree with article author was rate of change. IMO Pin should have never been added to standard library as it currently is. But async was rushed, for god knows what reasons.
I'm not sure who is it for, but if it's responsible for Pin and it's related unsoundness issues, that just makes me dislike it even more.
A language with BDFL could have, took a more principled stance and said no async until we prove Pin is safe.
> took a more principled stance
This is very insulting. Bugs are often found in every kind of software. Virtually no languages that exist, let alone popular ones, require proofs before landing new features.
To me it's not a bug. It's a foundational flaw. If Rust was a house, and a bug was a broken window, unsoundness issue would be water seeping into the foundation.
If standard library is unsound, that means pretty much everything derived from/relying on that functionality is unsound.
Adding unsoundness for the sake of pushing a feature out is just bad. It's cutting corners on essential things.
> they also could have said "ship it"
True. But if I know that BDFL is an asshat, then I avoid that project.
Here's why this matters. This response from you is much better! Because:
> If Rust was a house, and a bug was a broken window, unsoundness issue would be water seeping into the foundation.
Yes. Everyone agrees, in principle, that Rust being sound is an important property. Your criticism isn't actually about principles, it (appears to me, anyway) that it is about the specific methods in which we figure out if something is sound or not. You can argue that nothing should be added without formal proof, and that's a fine position to take, but at least it is a specific, actionable criticism that can be discussed directly.
By this standard, virtually all languages have "unprincipled" designers. This isn't even true of only async! We didn't (and still sort of don't) have a formal model of the borrow checker. So you can't really criticize async specifically in this way, you'd have to criticize the entire language.
The way I see unprincipled is two fold: 1) You're breaking your promise 2) In a similar situation behave differently
1) Pin was a problem from the start. Allowing it into std/core was a mistake. The fact they allowed an almost blatantly unsound feature is unprincipled.
I'm not 100% sure of the timeline, but near or before the release there were examples floating of a possible Pin unsoundness. And defense was, it's an obscure thing, no one would really use that in practice. The moment designer says, no one would use that in practice, is the moment they lost.
2) Yeah, I get async was a feature everyone wanted. By same measure, why not add self-referential struct. People want it. It's probably unsound but you can't tell. Maybe there exist a model that allows self-referntial structs.
Similar situation, different behavior
People do want it, and in fact, it is part of async, and directly related to the soundness issues you’re complaint about. The reason such things aren’t in stable is that, while people do want it, people wanted async more, and did the work. The work has to happen, features don’t just magically come into existence.
It doesn't appear to be unresolvable.
But what if the issue was unresolvable? Rust would either have to rollback a feature or basically say, we're sound, except for that part.
if you're doing modern stuff you just use a task-based parallelism lib and pass things by value with libs such as https://github.com/taskflow/taskflow, https://github.com/cameron314/concurrentqueue ...
The attention thing said by Bjarne by himself when asked on Reddit.
Rust is now doing the same. Few in the embedded space find it appealing, many of those who use C++ do (as it is certainly a cleaned-up C++, and a nice improvement in comparison), but too often not appealing enough to switch now, and some in the application space who don't know or don't remember the C++ lesson do adopt it now (sometimes out of sheer novelty) but will likely abandon it later for similar reasons C++ was largely abandoned in that space. So it is really competing for a pretty small and conservative niche -- albeit an important one -- and one with a strong incumbent. If it does very well, in 20 years we might find that 60% of the C++ space has switched over to Rust, and that's about it.
What Rust needs is focus, but it won't have it because I think some of its designers still believe in what C++ believed. That you can have a language that is both high-level and low-level, with the benefits of both and the downsides of neither.So it's being pulled in multiple directions, all while showing poor performance in the market (C++, at least, wasn't just hyped but actually popular). It's not even going after C++'s market seriously, but after the nonexistent market C++ thought it could occupy; the only market it seems to be actually competing over and doing well in is HN-front-page real-estate, the space formerly occupied by Ruby and Haskell. When I was at University in the late '90s, everyone was talking about Haskell will be the language of the future. With almost constant levels of hype, more than twenty years later, it still is. It turns out that for various reasons, when it comes to programming languages, hype and market performance can be completely out of sync for decades. Rust's designers need to choose between adoration and actual popularity. The latter will require some tough decisions. If it's going after the C++ market, it should make itself extremely appealing, irresistibly so, to C++ programmers.