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.
> 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++.
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
> 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.
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.
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 particularly shines: comptime metaprogramming, explicit memory allocators, and best-in-class C interoperability. Not to mention the ongoing work on compilation times
explicit memory allocators: these are easily made, there's nothing special about them, I use them all the time
best-in-class C interoperability: Nothing beats D's ImportC, where you can import a .c file as if it were a module. You can even use ImportC to translate your C code to D! https://dlang.org/spec/importc.html
I guess there are different levels of meta-programming. You can go really far in Rust/C++ too but I think Zig is really unique that you can write a function, which takes a type, it does some imperative mumbo-jumbo and spits out another type, doing exactly what you want, without having to think about restrictions, trait bounds, or whatever.
For example, here's comptime dependency-injection container, which notably, can be configured and extended, completely in comptime, and the final glue is something which in theory the compiler could optimize away too (no idea if it does).
https://github.com/cztomsik/tokamak/blob/main/src/container....
And regarding what they discuss in article, I did something similar for N-API, note how much you can do in few hundred lines, and I'd say that you can use it for most of what people do with napi-rs except that napi-rs is huge (and also unsafe, because it allows indirect recursion, which allows breaking all the rustc promises)
https://github.com/cztomsik/napigen/blob/main/src/napigen.zi...
I think in many ways D was just too ahead of it's time; Packaging the same feature set and abstraction level of C++ in much cleaner and saner package wasn't really seen at valuable at that time.
I think that if D were to be "re-release today" with a lighter syntax, and some coporate backing a-la GO/swift/typescript/carbon; It would find quite a bit of success.
Most components of the D standard library (Phobos) use garbage collection by default (when I last checked). This unfortunately removes it as a contender in the same space as Zig and Rust. And once you move to the GC space, there are a truckload of GC languages - it is the non-GC ones that are rare.
IMHO stdlib GC was one of the major barriers stopping D in the system programming space.
This is actually a great summary of Zig. I am with the author: I am too old and stupid to use Rust properly. Whenever I watch someone like Gjengset write Rust, I realize I am doing it wrong.
I am too old and stupid to not use Rust. I’m kidding of course, but the mental load of doing the things we used do in C++ is really noticeable once it’s gone.
honestly manually tracing lifetimes of pointers is not as hard in zig as C and definitely easier than C++. it would be nice to know for sure but for small and medium sized programs it's not a that hard? and not even "cheating" using arenas
I have seen this time and time again: first complain that C/C++ are too complex or lack feature X, new language is proposed, then sooner or later people find out that's it's not fast, expressive, flexible enough or imposes a nonstandard way of doing things (Rust), then back to C/C++ and few years after the cycle repeats.
Back in the day, before I had our robot overlords to write code for me, I would just use C++ as a fancy C with classes and a larger standard library. Or Boost as they have some fun and exciting things to play with.
Now, the robots do a good enough job at writing clean C++ without going too crazy that I just kind of let them do their thing and review the very readable code to keep them on the right path.
I can't even imagine the nightmare with something like a browser where you'd be pulling in C++ dependencies from all over the place and each having their own way of doing things. I mean, I get annoyed when C libs don't do the 'object to be operated on' as the first argument to functions so they can't be trivially wrapped in Python C-API extensions super easily using generators.
--edit--
Actually, this got me thinking, I was exploring using zig for a project (might still do, dunno) and came up with this meta-circular comptime peg grammar 'evaluator' to generate, at compile time, the parser for the peg grammar used to generate the parser for the runtime peg generator tool. Admittedly, I was pretty high when I cooked up this scheme with the robots but it seems to be viable...
Keep in mind you'll be using a different language in the future. All software is maintained for a given amount of time and then sunset. What matters is the lifecycle of the thing you're making now. Pick whatever is maintainable for that application and time frame.
Throwaway script? Use anything. A mobile app? Whatever gets it on the devices you're targeting today, that works for the life of the device/OS/etc. A backend API that will power a large platform? Something maintainable (by people other than yourself) for 3-5 years. Firmware for IoT that will remain in industrial systems for 20 years? Something that is well established and supported with a good number of other people who can fix it in the long haul.
Something interesting about your comment is that HN also has a post today (https://tigerbeetle.com/blog/2025-10-25-synadia-and-tigerbee...) about TigerBeetle's support for Zig and their reason for using Zig specifically talked about wanting something for a long time horizon:
> Investing in creating a database like TigerBeetle is a long term effort. Databases tend to have a long half life (e.g. Postgres is 30 years old). And so, while Zig being early in 2020 did give me pause, nevertheless Zig’s quality, philosophy and simplicity made sense for a multi-decade horizon.
If Zig's core developers decided tomorrow they wanted to do something else, would that result in the rest of the devs slowly leaving, and Zig being unmaintained after a couple years? Might be possible; but it would be impossible with C, C++, Java, etc. If you give me a choice between two products, one in Zig and one in Java, and I need to run it for two decades, I'm picking the Java one (and I dislike Java)
I like this take. While I've primarily lived in Python for much of my career (and I don't see that changing soon), I've tried to find reasons to use other languages in at least a hobby capacity so that I can (1) keep my learning muscles warmed up and (2) because they can often shape how I think about software in general.
Like the Alan Perlis (I think) quote goes: "A language that doesn't affect the way you think about programming is not worth knowing."
I wrote an article (this morning actually!) on picking up Rust to combat AI brain atrophy. My background is JVM-based (Kotlin), and my main contenders were Go vs Rust vs Zig.
My reasoning for settling on Rust:
If I wanted something more general-purpose and ergonomic, I'd stick with something like Kotlin, which has wider ecosystem support. Go could fit here too, but I've heard from more experienced folks that Go's simplicity can get limiting as codebases grow (and requires 100s of developers to be disciplined). Not impossible, just not as conducive.
But since I specifically wanted a performant systems language, I figured I'd go to the other extreme. So my choice was Rust or Zig. I eventually chose Rust (as complicated as Rust can seem) the borrow checker is pretty elegant once it clicks and provides the necessary safety net for a language I intentionally am choosing for more control.
Gotta admit there is something funny about a browser company saying Rust is not well suited for browser development given why it was created in the first place
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.
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
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.
Right tool for the job and all that.
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++.
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.
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.
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
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.
Do not do this.
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).
Go where I used to use Java.
Bun/Node for typescript/javascript, where each is appropriate, but I favor Bun for standalone application programming and local scripting.
The D programming language shines:
comptime: https://dlang.org/spec/function.html#interpretation
metaprogramming: https://dlang.org/spec/template.html#function-templates
explicit memory allocators: these are easily made, there's nothing special about them, I use them all the time
best-in-class C interoperability: Nothing beats D's ImportC, where you can import a .c file as if it were a module. You can even use ImportC to translate your C code to D! https://dlang.org/spec/importc.html
Performance: same as C and C++
For example, here's comptime dependency-injection container, which notably, can be configured and extended, completely in comptime, and the final glue is something which in theory the compiler could optimize away too (no idea if it does). https://github.com/cztomsik/tokamak/blob/main/src/container....
And regarding what they discuss in article, I did something similar for N-API, note how much you can do in few hundred lines, and I'd say that you can use it for most of what people do with napi-rs except that napi-rs is huge (and also unsafe, because it allows indirect recursion, which allows breaking all the rustc promises) https://github.com/cztomsik/napigen/blob/main/src/napigen.zi...
Most components of the D standard library (Phobos) use garbage collection by default (when I last checked). This unfortunately removes it as a contender in the same space as Zig and Rust. And once you move to the GC space, there are a truckload of GC languages - it is the non-GC ones that are rare.
IMHO stdlib GC was one of the major barriers stopping D in the system programming space.
What does it offer over Zig's translate-c?
ImportC can also import D modules, so C code can access the D code.
Now, the robots do a good enough job at writing clean C++ without going too crazy that I just kind of let them do their thing and review the very readable code to keep them on the right path.
I can't even imagine the nightmare with something like a browser where you'd be pulling in C++ dependencies from all over the place and each having their own way of doing things. I mean, I get annoyed when C libs don't do the 'object to be operated on' as the first argument to functions so they can't be trivially wrapped in Python C-API extensions super easily using generators.
--edit--
Actually, this got me thinking, I was exploring using zig for a project (might still do, dunno) and came up with this meta-circular comptime peg grammar 'evaluator' to generate, at compile time, the parser for the peg grammar used to generate the parser for the runtime peg generator tool. Admittedly, I was pretty high when I cooked up this scheme with the robots but it seems to be viable...
Throwaway script? Use anything. A mobile app? Whatever gets it on the devices you're targeting today, that works for the life of the device/OS/etc. A backend API that will power a large platform? Something maintainable (by people other than yourself) for 3-5 years. Firmware for IoT that will remain in industrial systems for 20 years? Something that is well established and supported with a good number of other people who can fix it in the long haul.
> Investing in creating a database like TigerBeetle is a long term effort. Databases tend to have a long half life (e.g. Postgres is 30 years old). And so, while Zig being early in 2020 did give me pause, nevertheless Zig’s quality, philosophy and simplicity made sense for a multi-decade horizon.
Like the Alan Perlis (I think) quote goes: "A language that doesn't affect the way you think about programming is not worth knowing."
My reasoning for settling on Rust:
If I wanted something more general-purpose and ergonomic, I'd stick with something like Kotlin, which has wider ecosystem support. Go could fit here too, but I've heard from more experienced folks that Go's simplicity can get limiting as codebases grow (and requires 100s of developers to be disciplined). Not impossible, just not as conducive.
But since I specifically wanted a performant systems language, I figured I'd go to the other extreme. So my choice was Rust or Zig. I eventually chose Rust (as complicated as Rust can seem) the borrow checker is pretty elegant once it clicks and provides the necessary safety net for a language I intentionally am choosing for more control.
(here's my article on learning Rust if folks are interested: https://kau.sh/blog/learn-rust-ai-atrophy/) - different angle from the linked article.