The C++ Killers (Not You, Rust)
wordsandbuttons.online
wordsandbuttons.online
This, very specifically, is the advantage these languages have over C++.
The benefit isn't the universe of things you can do (they're all Turing complete, you can do anything) - it's what the language stops you from doing. This is the thing the C++ committee never understood or at the very least never appreciated.
Newer languages are adding friction or dropping altogether things that you rarely or never want to do, to more tightly constrain the space of possible actions to the set of desired actions.
People make mistakes.
We can make tools which reduce the frequency of certain classes of mistakes (c++ has a few of them now as well)
Those are pretty cool tools.
On a leash? What? ... [if only I could work in a] consequence-free environment, I'll be sound as a pound!
In my old age, I find the more permissive a language is, the more painful it is to code in long term. Perl is great for simple things, but C++ was a vast improvement because it catches a lot of nonsense that Perl will compile just fine.
And debugging is so expensive that eventually writing code fast is near worthless. Whatever you gain you more than pay for in debugging afterwards.
C++ unfortunately doesn't go far enough.
One could technically also get memory and reference safety this way. Which is the opposite of what Rust does for example, where it defaults to do a particular model of referencing memory and makes using any other painful.
It also does not have any constraints on timing or redundancy if necessary.
Automate some of this handling but still keep it explicit and you have a potential winner.
There's a balance.
Rust is not a simple language.
Lisp is also a simple language.
Lua is simple as well (well… maybe not…)
JavaScript is not.
C++ is not.
It's not that C is simpler, it's less expressive.
I don't think this answers parents question though, which is what does it mean for a language to be simpler? I think that's a good question. This is just a list of examples.
It almost seems like simple is a bad concept applied to languages because what's simple and complex is the idea you're trying to express, accurately, in its totality - not necessarily the language.
The fewer ways there are to express an idea, the simpler the language is.
Simple languages do not imply simple software (look at lisp)
I hesitate to even guess what the findings would look like, but I bet it’d be interesting.
Meanwhile with ocaml you need to understand type theory, type inference, algebraic data types, the module system, maybe row poly, (insert a bunch of other things), and now also algebraic effects. And there's no guarantee that the well formed logic of your domain problem is compatible with the type theory your language is using (although, adt + generics almost always does the job if you take a minute).
That being said, the way that's being expressed here does leave something to be desired. Like, if someone doesn't jive well with static techniques that's one thing. But I've never really understood decrying people who get it as suffering from some sort of Stockholm syndrome.
Even though I don't agree with the dynamic camp, I like advocating for it because I think there are scenarios where there is something there.
However, the position that the static camp is somehow against freedom and morally wrong is pretty weird to me.
Okayish was fine or even necessary in the past but the industry has matured to the point where we need more purpose built tools for more specific projects.
Rust is going to be necessary but also zig, hylo, vale, p, Odin, and jai (assuming we ever get a release date). A language able to do everything that c++ can is almost definitely only able to do it all okayish.
You can add other constraints (e.g. temporal constraints) and get similar benefits, on top of the above.
Yes, there are security issues beyond memory safety bugs. But these are the issues that are most regularly turned into the most serious exploits and they are hellishly common.
All systems security is about layered defenses. "Oh, log4j exists" is not a compelling reason to avoid changes that can mitigate very large portions of security risk.
There are places where you'll truly never encounter untrusted input and a crash is just as bad as blasting off and performing whatever unexpected computation, but that's nowhere near the entire existing C++ landscape.
And it explicitly introduces undefined behaviour aka "memory safety bugs".
And a large fraction of the problems that lead to security situations. Worse, they are often so subtle that they stay in a codebase for decades.
> and replacing them by an immediate shutdown is hardly a very useful improvement on program quality.
That's a pretty absolutist statement about something that's very context dependent.
[0] I meant what I said.
I find it interesting because until about three years ago, C++ was always on the other side of this argument. We fight about static type systems. You could shout at the compiler that you know that your code is correct even though the type system doesn't pass. Why does the committee think it knows better than me! Everything is just bits after all!
Now we are on the other side. C++ people saying "bro I totally promise I'll initialize this data member before it is used, stop making me initialize it in my constructor"
C++ has never said this - if a type has a constructor, that constructor will always be used in a data member (or elsewhere).
You can absolutely write a type like this.
class Foo {
public:
Foo() {} // never initialized x
int x;
}
And then using it like this Foo f;
bar(foo.x); // oops
"But my types are well designed" is the usual response to "why the heck does the language allow you to quietly expose yourself to UB in this way?"Any instance of Foo will run Foo's constructor because Foo has one. The problem is that that instance of Foo won't definitely have x initialized, because int doesn't.
Plus, there are stl types that don't guarantee initialization of members. So it isn't like only ever resting on top of stl types is sufficient. std::optional has a non-default constructor but it can happily blow up because of a read of uninitialized data.
And the fact that this is the silent default behavior in C++ is wild to me. Even in languages where it is possible to leave data in an uninitialized state, you should need to loudly signal it.
I agree, totally. Backwards compatibility is a cruel mistress.
You can do this in Rust if you want! You just have to use unsafe { mem::uninitialized() } or even better, the newer unsafe { mem::MaybeUninit::uninit() }
The whole point is that you probably don't ever want to have an uninitialized variable you can access willy-nilly, and if you do, you should be very explicit.
Even your statement about C (and C++) isn't quite accurate, right, because anything static is guaranteed to be initialized to zero on creation. So while `int x` is a free for all, `static int x` is gonna be zero. Another thing people shouldn't have to think about!
Principle of least surprise.
Congrats if you never write bugs. For the rest of us, we will use the widely available data that demonstrates that these bugs recur over and over and over and over even in organizations with strong developers, strong testing culture, and where the use of static analyzers and fuzzing is widespread.
Yes, C also has these problems. Both C and C++ represent significant safety risks, despite powering some of our absolute most security critical applications (the linux kernel and our web browsers). Other languages don't give you these footguns.
They might know how to design a language such that it tends to produce exceptionally readable codebases, good performance, and improved safety, though. Maybe not all three at once, but some mix of those that’s better than existing languages, perhaps.
So it may be very true that for their work it’s all the same whether they use C++, or Python with numeric libraries, or some niche DSL, or a macroassembler.
But use of C++ is much broader than pure compute, so this perspective does not generalize to C++ or Rust as a whole.
Little by little, domains where either C or C++ would be the option to go during the 1990's, with exception of areas where VB and Object Pascal (Mac/PC variants) were enjoying adoption, have been slowly taken away from them.
Bjarne created C with Classes for his distributed systems research at Bell Labs, nowadays the majority of CNCF project landscape is written into something else.
C++ GUI frameworks were all over the place during the 1990's, nowadays one has to go to third parties, as platform vendors rather focus on managed languages. Even C++/WinRT going into maintenaince is an acknowledgemnt from Microsoft that outside Redmond XAML / C++ was a failure in regards to adoption.
Long term we might be left with LLVM, GCC, Unreal, Skia, CUDA, and a couple of other key projects that keep C++ relevant and that is about it.
There are two typos in this statement, one is "uin16_t" should have been "uint16_t", the other is that the "+" should have been "*". Searching for 1794967296 yields this answer:
https://stackoverflow.com/questions/18161443/type-casting-wh...
To you. There are pleeenty of people who want to write performant code in a safe manner.
Take C++ vs. Rust, for instance. If I look at this from a business perspective:
- Rust compiler can likely help confirm reference correctness, so this is a plus. - Rust language exchanges the cognitive load of memory allocation for tracking reference ownership, so this is a neutral. (In C++ anything that has access to the pointer can technically "own" it so there is no need to track function call traces for ownership, but lifetimes do need to be analyzed against the semantics of the program. Potato, po-tah-to.) - The pool of Rust developers available to work on a project is much smaller.
If I'm writing software where memory safety is of high importance and I can afford to take the risk with a smaller developer pool, Rust makes sense. If I'm writing a game? It's going to make far more business sense to hire a bunch of C++ developers that can work with Unreal or C# developers to work with Unity or Python developers to work with Godot or whatever.
And for real mission-critical software memory allocation isn't used so in those cases Rust has zero advantages. (Real mission-critical software lays out a static memory map up front to avoid exactly the problems Rust is trying to avoid but to also ensure real-time & predictable response times.)
So we're left with niche software like OpenSSL or similar that can benefit from Rust. But it's more likely that we want a language that supports proofs of correctness (think Coq or seL4) in those cases and Rust can't even support that.
So why choose Rust at all?
For example, C++/11 introduced UTF8 string literals. Great feature which does what you’d expect – declare a string literal in source code, get a const pointer to null-terminated array of utf-8 bytes.
Then a decade later, in C++/20 they refactored these UTF8 literals to evaluate into const pointers to the new incompatible data type, char8_t.
It’s so bad that compiler developers had to implement switches to disable the new BS. Unfortunately, these switches are incompatible across compilers, -fno-char8_t in gcc, /Zc:char8_t- in msvc.
As simple as that.
Many of the modern features aren't even exposed to the comunity as preview features before being voted into the standard.
If C++ was really all about speed then we'd have destructive move letting you pass unique_ptr in a register without compiler trickery. The fundamental number one constraint on new C++ behaviors is ABI compatibility. The rest is secondary.
Something doesn't have to be enshrined into the standard to be a major driving point in the language.
The very existence of Carbon is due to the c++ committee not wanting to break abi compatibility.
And they do care deeply - here's a post from a C++ committee member discussing the issue: https://cor3ntin.github.io/posts/abi/
[1] Evidenced by the rest of the post talking about the committee, and referring to people a couple messages up thread:
> And yet they can't update the standard library types to not be slow as hell because of ABI concerns.
etc.
My two cents: it is improbable that C++ will be ever replaced because it is a mastodon as a programming language: super complex, where complex includes complexity as difficulties and also its vastness. This doesn't mean that it will increase its usage since it is common nowadays to use specific programming languages (e.g. Python) for specific purposes and rely on C++ and others for very specific areas. Personally, I really liked SWIG [1] as a wrapper and interface generator. Don't know how much it is used today.
Other experience but similar conclusion than the article.
I consider myself far from what is considered professional C++ knowledge, but for cryptography I always relied on Crypto++ [1] and that made me decide for the use of C++, at least partially. I think we can apply the same thinking for JavaScript or TypeScript, personally I don't like too much those programming languages but if I need to write a RESTful backend I go that route because they have good modules for that or sometimes I decide for Python.
I very much want to hear that story
I'm almost afraid to ask, but I'd love to know: are there any Algol 68 projects in active use? Anyone have war stories of maintaining them (bug fixes, new features, improvements to interface with more modern systems) in the last couple decades?
anyway, as i was hired as a microcomputer specialist, and as two dec10 systems programmers had ducked it, i simply said "no can do" - a valuable lesson.
this is what i like about HN - recalling things i had completely forgotten!
And yes, I do agree the fact that I know so much minutiae about those languages is part of the reason why I'm reluctant to go for something else I have a more shallow knowledge of. But that level of attention to detail is also what allows me to deliver high-quality code that does exactly what I intend it to do.
You have to, not you need to. Of course I know plenty of them (so much that I have won IOCCC a decade ago), but most of them are just pure hindrances and do not contribute to anything positive.
My fav Go feature is the memory ballast - it's real, lots of go programs have command-line to set it up, and no one cares about it anymore
https://blog.twitch.tv/en/2019/04/10/go-memory-ballast-how-i...
Those redundant multiplications cannot be removed without fast math because floating-point operations are not associative.
There are well-known optimal ways to evaluate a polynomial, namely Horner's and Estrin's schemes.
The C++ Killers (Not You, Rust) - Feb 2023 (59 comments) : https://news.ycombinator.com/item?id=34792932
It seems author has published the article last year but moved it to his blog now
> Improving the efficiency of algorithms for fundamental computations can have a widespread impact, as it can affect the overall speed of a large amount of computations. Matrix multiplication is one such primitive task, occurring in many systems—from neural networks to scientific computing routines. [...] We further showcase the flexibility of AlphaTensor through different use-cases: algorithms with state-of-the-art complexity for structured matrix multiplication and improved practical efficiency by optimizing matrix multiplication for runtime on specific hardware. Our results highlight AlphaTensor’s ability to accelerate the process of algorithmic discovery on a range of problems, and to optimize for different criteria.
And I'll emphasis this sentence, as it seems to be the main goal/critics of the author in this post:
> improved practical efficiency by optimizing matrix multiplication for runtime on specific hardware.
Not only is that insane code and both my compiler and static analysis go for my throat, it's also not true. I think the argument is supposed to be about unsigned integer overflow, but the numbers don't add up. The big negative number wraps to 63744. And the sum (100K) wraps to 34464.
> created: January 17, 2020
> number of submissions 10798
Do you auto post from some aggregation script, mind disclosing why you do this, what sources do you use?
This is a pretty annoying thing to do considering someone took the time to read through all this.
Also not original, I’ve seen posts in here like this 3 times already