Years ago, when I initially picked up Rust, I loved it. It does a lot of things right. At the same time, though, I knew there was a possibility of it going wrong in two opposite directions:
1. Developers balked at being required to take on the cognitive load required to allow GC-less memory management
2. Developers wore their ability to take on that cognitive load as a badge of honor, despite it not being in their best interest
I eventually came to the decision to stop developing in Rust, despite its popularity. It is really cool that its creators pulled it off. It was quite an achievement, given how different it was when it came out. I think that if I had to implement a critical library I would consider using Rust for it, but as a general programming language I want something that allows me to focus my mental facilities on the complexities of the actual problem domain, and I felt that it was too often too difficult to do that with Rust.
It's not quite a fully formed argument, but I'm coming to the view that Rust mostly requires less cognitive load than other languages. I'm coming at this from the perspective of "cognitive load" meaning, roughly "the measure of the number of things you need to keep in working memory". Rust is no doubt difficult to learn, there are many concepts and a lot of syntax, but when you grasp it cognitive load is actually lower. Rust encodes so much more about the program in text than peer languages so there are fewer things to keep in your head. One good example of this is pointer lifetimes in Zig and C which you have to keep in your head, whereas in Rust you don't.
My own appreciation for Rust is rooted in humility. I know I'm an overgrown monkey prone to all kinds of mistakes. I appreciate Rust for helping me avoid that side of me
The mentality around lifetimes is different in Zig if you are using it for the correct types of problems.
For example, a command line utility. In a CLI tool you typically don't free memory. You just allocate and exit and let the OS clean up memory.
Historically compilers were all like this, they didn't free memory, they just compiled a single file and then exited! This ended up being a problem when compilers moved more into a service model (constant compilation in the background, needing to do whole program optimization, loading into memory and being called on demand to compile snippets, etc), but for certain problem classes, not worrying about memory safety is just fine.
Zig makes it easy to create an allocator, use it, then just free up all the memory in that region.
I've been having an absolutely great time with Rust's bumpalo crate, which works very similarly. The lifetime protection still works great, and it's actually a lot more permissive than normal Rust, since it's the same lifetime everywhere.
The sad exception is obviously that Rust's std collections are not built on top of it, and neither is almost anything else.
But nevertheless, I think this means it's not a Zig vs Rust thing, it's a Zig stdlib vs Rust stdlib thing, and Rust's stdlib can be replaced via #[no_std]. In the far future, it's likely someone will make a Zig-like stdlib for Rust too, with a &dyn Allocator inside collections.
> In the far future, it's likely someone will make a Zig-like stdlib for Rust too, with a &dyn Allocator inside collections.
This exists in the nightly edition of Rust, but is unlikely to become a feature in its current form because the alternative of "Storages" seems to be a lot more flexible and to have broader applicability.
was where i got last year. this december im doing a "prototype" which means its going to be done in zig and im going to clear sone difficult hurdles i couldn't do last year.... also accepting sponsors, details on page.
also disclaimer, im using heavy amounts of ai assistance (as implied in the preview video)
> Rust is no doubt difficult to learn, there are many concepts and a lot of syntax
People love to say this, but C++ is routinely taught as a first programming language to novice programmers (this used to be even more clearly the case before Java and Python largely took on that role) and Rust is undoubtedly simpler than C++.
C++ as First Language seems like an especially terrible idea to me. Maybe I should take a few months and go do one of those courses and see whether it's as bad as I expect.
The nice thing about Rust as First Language (which I'm not sure I'd endorse, but it can't be as bad as C++) is that because safe Rust ropes off so many footguns it's extremely unlikely that you'll be seriously injured by your lack of understanding as a beginner. You may not be able to do something because you didn't yet understand how - or you might do something in a terribly sub-optimal way, but you're not likely to accidentally write nonsense without realising and have that seem to work.
For example yesterday there was that piece where the author seems to have misunderstood how heap allocation works in Rust. But, in safe Rust that's actually harmless. If they write their mistake it won't compile, maybe they figure out why, maybe they give up and can't use heap allocation until they learn more.
I haven't thought too hard about Zig as first language, because to me the instability rules that out. Lecturers hate teaching moving targets.
As somebody that "learned" C++ (Borland C++... the aggressively blue memories...) first at a very young age, I heartily agree.
Rust just feels natural now. Possibly because I was exposed to this harsh universe of problems early. Most of the stupid traps that I fell into are clearly marked and easy to avoid.
It's just so easy to write C++ that seems like it works until it doesn't...
That's true, but as someone that doesn't do much rust, C++ is a language where there are fewer restrictions and you can use little parts of the language, whereas Rust is supposed to be a simpler language overall, but with more concepts to learn up-front to prevent things that happen where there are no rules....
You can use "little parts of the language" in Rust too; the cleanest and most foundational part of Rust is pure value-based programming with no mutability or referencing at all, much like in a functional language (but with affine types!). Everything else is built quite cleanly on top of that foundation, even interior mutability which is often considered incredibly obscure. (It's called "interior" because the outer cell's identity doesn't really mutate, even though its content obviously does.)
You can absolutely make a complete, featureful program in Rust without naming a single lifetime, or even without dealing with a single reference/borrow.
But Rust is a dramatically smaller language than C++. The various subsets of C++ people usually carve out tend to be focused on particular styles of programming, like “no exceptions” or “no RTTI”. Notably never things like “signed integer overflow is now defined”, or “std::launder() is now unnecessary”.
Discussions about Rust sometimes feel quite pointless because you can be several replies deep with someone before realising that actually they don't know much about the language and their strongly-held opinion is based on vibes.
And I didn't even break out the function chaining, closure and associated lifetime stuff that pervades the Rust GUI libraries.
When I can contrast this to say, ImGui C++:
ImGui::Text("Hello, world %d", 123);
if (ImGui::Button("Save"))
MySaveFunction();
ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
which looks just slightly above C with classes.
This kind of blindness makes me wonder about what universe the people doing "Well Ackshually" about Rust live in.
Rust very much has an enormous learning curve and it cannot be subsetted to simplify it due to both the language and the extensive usage of libraries via Cargo.
It is what it is--and may or may not be a valid tradeoff. But failing to at least acknowledge that will simply make people wonder about the competence of the people asserting otherwise.
> Exactly. Claims like "even without dealing with a single reference/borrow."
> When you have this stuff in "Hello World"
Might be worth reading simonask's comment more closely. They said (emphasis added):
> You can absolutely make _a_ complete, featureful program in Rust without naming a single lifetime, or even without dealing with a single reference/borrow.
That some programs require references/borrows/etc. doesn't mean that all programs require them.
The rust code you pasted doesn't show any lifetime.
The `&f` in your imgui example is equivalent to the `&mut age`.
Are you just comparing the syntax? It just take a couple of hours to learn the syntax by following a tutorial and that `&mut` in rust is the same as `&` in C, not to mention that the compiler error tell you to add the `mut` if it is missing.
Also 0..=120 is much more clear than passing to arguments 0.0f, 1.0f. it makes it obvious what it is while looking at the imgui call it isn't.
This seems like a very strange position, code written for Rust in 2015 still works, and in 2015 Rust just doesn't have const generics†, or async, or I/O safety, so... how is that not a subset of the language at it stands today ?
† As you're apparently a C++ programmer you would call these "Non-type template parameters"
I gave up on a C++ after trying to learn on and off for years. LNK1009 still haunts me in my sleep. I am now an avid self-taught rust programmer and I feel like I have the power to create almost anything I can imagine using rust. This is great for hobby people
I belonged to the generation that graduated into the rising dotcom boom. Around that time, lots of universities taught C++ as the first serious language. (Some still started with Pascal.)
The main thing a lot of had going for us was 5-10 years of experience with Basic, Pascal and other languages before anyone tried to teach us C++. Those who came in truly unprepared often struggled quite badly.
I did. Though a few years earlier I had attended a class where Pascal was used (however, it was not the main topic, it was about robotics). C++ was what I learned first in a "real" computer science class. In later years, we did move to Java. And I initially hated Java :D but ended up making a career using it.
Java in the 2000's was a poor language, but after Java 8, it has become decent and I would say the latest version, Java 25, is a pretty good language.
This thread is about Zig though! I want to like Zig but it has many annoyances... just the other day I learned that you must not print to stdout in a unit test (or any code being unit tested!) as that simply hangs the test runner. No error, no warning, it just hangs. WTF who thinks that's ok?!
But I think Zig is really getting better with time, like Java did and perhaps as slowly. Some stdlib APIs used to suck terribly but they got greatly improved in Zig 0.15 (http, file IO and the whole Writergate thing), so I don't know, I guess Zig may become a really good language given some more time, perhaps a couple of years?!
I learned C++ first. Like many I wanted to make games so I started programming before high school. I think our first high school classes were also in C++ tbf.
Oh, I do have a fully-formed argument for this that I should probably write out at some point :)
The gist of it is that Rust is (relatively) the French of programming languages. Monolingual English speakers (a stand-in here for the C/C++ school of things, along with same-family languages like Java or C#) complain a lot about all this funky syntax/semantics - from diacritics to extensive conjugations - that they've never had to know to communicate in English. They've been getting by their whole life without accents aigu or knowing what a subjunctive mood is, so clearly this is just overwrought and prissy ceremony cluttering up the language.
But for instance, the explicit and (mostly) consistent spelling and phonetics rules of French mean that figuring out how to pronounce an unfamiliar word in French is way easier than it is in English. Moods like the imperative and the subjunctive do exist in English, and it's easier to grasp proper English grammar when you know what they are. Of course, this isn't to say that there are no parts of French that an English speaker can take umbrage at - for example grammatical gender does reduce ambiguity of some complex sentences, but there's a strong argument that it's nowhere near worth the extra syntax/semantics it requires.
On top of all that, French is nowhere near as esoteric as many monolingual Anglophone learners make out; it has a lot in common with English and is easier to pick up than a more distant Romance language like Romanian, to talk of a language in a more distant family (like Greek or Polish). In fact, the overlap between French and English creates expectations of quick progress that can be frustrating when it sinks in that no, this is in fact a whole different language that has to be learned on its own terms versus just falling into place for you.
Hell, we can take this analogy as far as native French speakers being far more relaxed and casual in common use than the external reputation of Strictness™ in the language would have one believe.
>My own appreciation for Rust is rooted in humility. I know I'm an overgrown monkey prone to all kinds of mistakes. I appreciate Rust for helping me avoid that side of me
I think we've heard these arguments ad nauseum at this point, but the longer I use Rust for ensuring long-term maintenance burden is low in large systems that I have to be absolutely, 10,000% correct with the way I manage memory the more it seems to reduce the effort required to make changes to these large systems.
In scenarios where multiple people aren't maintaining a highly robust system over a long period of time, e.g. a small video game, I think I'd absolutely prefer Zig or C++ where I might get faster iteration speed and an easier ability to hit an escape hatch without putting unsafe everywhere.
> I'm coming to the view that Rust mostly requires less cognitive load than other languages.
This view is only remotely within the bounds of plausibility if you intended for "other languages" to refer exclusively to languages requiring manual memory management
- `&mut T` which encodes that you have exclusive access to a value via a reference. I don't think there is any language with the same concept.
- `&T` which encodes the opposite of `&mut T` i.e. you know no one can change the value from underneath you.
- `self`/`value: T` for method receivers and argument which tells you ownership is relinquished (for non-Copy types). I think C++ can also model this with move semantics.
- `Send`/`Sync` bounds informing you how a value can and cannot be used across thread boundaries. I don't know of any language with an equivalent
- `Option<T>` and `Result<T, E>` encoding absence of values. Several other languages have equivalents, but, for example, Java's versions is less useful because they can still be `null`.
- Sum types in general. `Option<T>` and `Result<T, E>` are examples, but sum types are amazing for encoding 1-of-N possibilities. Not unique to Rust of course.
- Explicit integer promotion/demotion. Because Rust never does this implicitly you are forced to encode how it happens and think about how that can fail.
All of these are other ways Rust reduce cognitive load by encoding facts in the program text instead of relying on the programmer's working memory.
In languages like Java their version of the Billion Dollar mistake doesn't have arbitrary Undefined Behaviour but it is going to blow up your program, so you're also going to need to track that or pay everywhere to keep checking your work - and since Rust doesn't have the mistake you don't need to do that.
Likewise C# apparently doesn't have arbitrary Undefined Behaviour for data races. But it does lose Sequential Consistency, so, humans can't successfully reason about non-trivial software when that happens, whereas safe Rust doesn't have data races so no problem.
Neither of these languages can model the no-defaults case, which is trivial in Rust and, ironically, plausible though not trivial in C++. So if you have no-defaults anywhere in your problem, Rust is fine with that, languages like Go and Java can't help you, "just imagine a default into existence and code around the problem" sounds like cognitive load to me.
The problem Cloudflare had, and from what it seems, still have is that they don't actually test software at small volumes before global deployment. I would guess that two outages in quick succession means the voices saying "You need to test everything properly" might win, but perhaps not.
The Billion Dollar mistake is about not even having the distinction shown in the commit you linked. In languages with this mistake a Goose and "Maybe a Goose or maybe nothing" are the same type.
> I eventually came to the decision to stop developing in Rust, despite its popularity
It's also not popular for a language that old. It's roughly as popular as Ada was when it was the same age Rust is today (there may not have been as many projects written in Ada then, but there were certainly much bigger/more important projects being written in Ada then). It's not nearly as popular as C, or C++, or Java, or C#, or Go were at that age.
The relatively small number of developers who program in Rust, and the smaller still number of them who use it at work, are certainly very enthusuastic about it, but an enthusiastic "base" and popularity are very different things.
The only lists it's topped are for likeability by users, where it was followed by Elixir and Clojure. If we go by the meaning of popularity that suggests how many people use these languages, let alone professionally, their ratings are quite low (e.g. https://www.devjobsscanner.com/blog/top-8-most-demanded-prog...). Considering how old Rust is, the numbers are significantly lower than of any language that's become truly popular (as in widespread). An old language used by so few people can be many things, but "popular" isn't one of them.
You're citing language demand as a result of incumbent industry usage. That's an inherently weighted metric because existing products are not (contrary to what some Rust zealots might want) going to be rewritten in Rust for no reason.
i.e, it's not rocket science - languages with 10-20+ year history are embedded in the industry. News at 11. ;P
Popularity - as the term is actually used - is one where Rust is fine.
I was comparing Rust to the popularity of other languages at the same age. Its adoption rate is not fine for a language that old if it aims to one day be as popular as C++ is today (or even as popular as Go is today).
The only modern language you listed is Go, which had Google backing it and is a simpler language overall. The rest achieved their popularity when the industry was smaller and there wasn't as much competition.
Those of us who were programming in the nineties and before remember there was a lot of competition [1]; not less than today. It's just that not much of it survived to this day in any popular form. Also, C++ didn't have any stronger backer than Rust, at least not at first. (BTW, Go's introduction was closer in time to Python's or Java's than it is to today; both Go and Rust are already fairly old languages)
[1]: In the application space, there were VB, Delphi, Smalltalk, and a host of other so-called "RAD languages". In the scripting space, Perl was dominant. In the low-level space, we had the entire Pascal family, with Ada and, to a lesser extent, Oberon.
Rust does not require GC-less memory management. It supports reference counting out of the box, and reference counting is a kind of GC. It's not inherently any harder to use than Swift (another memory-safe language) which plenty of average developers use to code for Apple platforms.
I don’t think it’s a useful observation. Lots of people come to Rust from OOP languages and try to make everything `Arc<dyn Interface>`, and it immediately fails, to their great frustration.
It's fine as long as the graph of references is immutable, or is unidirectional/acyclic with unique ownership.
If you have backreferences or "parent pointers", you need `Arc<Mutex<...>>` or `Rc<RefCell<...>>`, and then you run into trouble as you encounter the same node multiple times while traversing the graph, because you cannot hold a mutex lock or mutably borrow `RefCell` twice in the same call stack.
The solution with much less resistance in Rust is to go for a data-oriented representation. If you really need an actual graph of objects, separate the node data from the topology metadata, and refer to the nodes using an ID or index. (As an extra bonus, this also gives you much better cache locality.)
My experience has been the opposite. I came from Python and Typescript and the initial amount of reading and fighting with the compiler was very frustrating but I understood one thing that sets Rust apart - I write code with almost the same level of bugs as a seasoned Rust developer. That is a win for years to come as team grows and software gets old. I will bet on it again and again.
Now I mostly generate code with coding agents and almost everything I create is Rust based - web backend to desktop app. Let the LLM/agent fight with the compiler.
> Zig where I used to use C/Rust (but admittedly I spent the least time here).
I really don't understand how that fit with the “I want something that allows me to focus my mental facilities on the complexities of the actual problem domain”.
For low-level stuff, Rust allows to offload the cognitive load of maintaining the ownership requirements to the machine. On the opposite, Zig is exactly like C as it forces you to think about it all the time or you just shoot yourself in the foot at the first opportunity…
For stuff that can be done with managed languages, then absolutely, the GC allows to completely ignore that aspect, at the cost of some performance you don't always care about because how fast the modern hardware is.
1. Developers balked at being required to take on the cognitive load required to allow GC-less memory management
2. Developers wore their ability to take on that cognitive load as a badge of honor, despite it not being in their best interest
I eventually came to the decision to stop developing in Rust, despite its popularity. It is really cool that its creators pulled it off. It was quite an achievement, given how different it was when it came out. I think that if I had to implement a critical library I would consider using Rust for it, but as a general programming language I want something that allows me to focus my mental facilities on the complexities of the actual problem domain, and I felt that it was too often too difficult to do that with Rust.