Picking up a new programming language
I wanted to give Rust a fair try, the last time I didn’t go far and the only stuff I truly remember about Rust is this tiny detail, which still puzzles me:
fn main() {
let a = 2; // a is an integer
// a = "2"; // failure: sting assignment to an integer, ok
let a = "2"; // compiles... WTF!? Yes it's re-defined, but this design choice...
}
This tiny snippet compiles fine, with unused warnings. A warning free version on Compiler Explorer Or use this full link just in case
Zig philosophy
I discovered Zig reading somewhere that it wanted to be a better C, and I chuckled (like really, how robust are their shoulders to support their heads while saying this?), but then wanted to have a look at its official website to confirm this by myself, just to discard it from my programming languages to check list.
Actually, I realized quickly it has many good ideas, not only stuff you would expect from modern programming languages (readable compile time stuff for instance), but also some specifics (avoiding hidden control flow / memory allocations).
Everything’s monolithic.
Zig comes with a compiler (no shit…), a standard library, but also a package manager, unit tests framework, formatter, fuzzer, …
I had no strong opinion about this, but the more I dig into Python and see people using multiple package managers, formatters and tests frameworks in a single project without noticing it or understanding why it’s fishy and then complaining that nothing’s compatible, the more I think it’s not a bad idea to centralize stuff.
Installing Zig means downloading and extracting a ~55 MB (at the time of writing) .tar.xz and… that’s it.
$ wget https://ziglang.org/download/0.17.0/zig-x86_64-linux-0.17.0.tar.xz
--2026-10-18 08:47:32-- https://ziglang.org/download/0.17.0/zig-x86_64-linux-0.17.0.tar.xz
Resolving ziglang.org (ziglang.org)... 2a01:4f9:3051:4bd2::2, 65.109.105.178
Connecting to ziglang.org (ziglang.org)|2a01:4f9:3051:4bd2::2|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 57332648 (55M) [application/octet-stream]
Saving to: ‘zig-x86_64-linux-0.17.0.tar.xz’
zig-x86_64-linux-0.17.0.tar.x 100%[===============================================>] 54.68M 6.18MB/s in 9.6s
2026-10-18 08:47:42 (5.69 MB/s) - ‘zig-x86_64-linux-0.17.0.tar.xz’ saved [57332648/57332648]
$ ls -lh zig-x86_64-linux-0.17.0.tar.xz
-rw-r----- 1 jp jp 55M Oct 2 21:55 zig-x86_64-linux-0.17.0.tar.xz
$ tar xf zig-x86_64-linux-0.17.0.tar.xz
$ zig-x86_64-linux-0.17.0/zig version
0.17.0
Congratulation, you installed zig!
Oh btw, why 55 MB, isn’t it quite heavy? After decompression, the zig binary takes roughly half of the extracted weight. Something I didn’t mention is that Zig embedds a C compiler (note that Zig does not transpiles to C though). The rest of the weight mostly comes from the libc (42% you cannot compete with this).
I left the raw dust output because maybe you noticed on the screenshot, the presence of multiple C libraries, and maybe also the unexpected presence of mingw in a x86_64-linux so, cannot the Zig maintainers properly pack their artifacts or is there a real reason?
Zig is actually a cross-compiler.
Cross-compilation in Zig is still a topic I need to deep dive into. Zig can cross compile for many targets (different BSD flavors, arm-linux-gnueabihf, the dreaded Windows, …). Actually the Zig build system can be a drop in replacement to cmake, autotools, …
For which exacts targets can you compile you may ask? Many! This time, no full output, because…
$ zig targets | wc -l
35009
Zig respects the C ABI. Zig competes sanely with C, it embraces C not trashes it. The decades of legacy still lives on, and Zig can help you with it instead of telling you to re-write everything with the new shit.
Killer features
Incremental compilation
The idea is simple: compile only what you need to compile: if you modify one local variable without side effects, do you need to recompile the full project?
This is the kind of black magic I didn’t even realize it was possible before learning the Zig core team worked on it. I mean, binary patching is a thing (and, no I don’t mean asking a LLM to not modify some specific sources and… noticing this fucker patched the binary instead). But, hotfixing with the linker, like really? You need to know about dependencies, side-effects, linker sections, …
If you want to dive in this topic, Matthew Lugg from the core team wrote a blog post about this; definitely worth multiple reads.
Oh, btw yes, the core team implemented their own linker.
Optimization
We’re talking about custom linker, custom C compiler, everything done the Zig way, so what we just throw away decades of optimization in other toolchains? Actually no: LLVM is still used as the backend in optimization mode (--release=fast)
The custom backend is used for debugging, incremental compilation, … but the LLVM one is used (so far?) for optimization.
For the size optimization side, the standard library is optional, you can go bare-metal.
Simplicity
This language actually focus on simplicity, or in other words, forcing the user to understand what’s going on.
You want memory? Ok, how do you want it allocated?
You want to print something? Oh buffered print this time, fine, where is your buffer?
We constantly hear about C++ devs arguing that there is no overhead in C++ which can be true, if you know exactly what’s going on.
Either perf says: nope, it’s slower than you thought, or you hear a dev mumbling something like “ok this operator overload so, this constructor will be called, then Short String Optimization kicks in, …” and after a few minutes, arguing against perf results.
In Zig, reading the code gives you clear hints on what’s going on. For instance, if a function needs to allocate memory, it will likely take an allocator as argument.
The best of all worlds
Zig feels like having the best of all worlds:
It can feel like an interpreted language, without compilation time, but with compilation checks before blindly running a binary crashing with a parse error.
Fair comparisons show C-runtime performances levels.
If your code is too slow, measuring will likely not pinpoint to unknown regions, where you ponder why a strlen coming directly from GCC is magically called, but more on your handwritten code.
Drawbacks of Zig
None, next section… No? Ok.
Evolving fast
Zig is under heavy development. The core team regularly breaks stuff and removes features. Blindly upgrading to the next release can be a breeze, where the formatter will do the job for you (no kidding) or a painful death.
Try to keep an eye on the devlog, the forums or ideally on the repo on codeberg for instance to have a feeling on what you should already modify or stop doing.
Documentation
The documentation is really poor (let’s troll: there is no documentation), but the sources are readable. I mean it: I have a fair C or C++ experience, using these professionally for most of my career. For me, opening the C standard library is doable, the C++ one is a no-go, always ending up with more questions, assuming I found what I was looking for.
The Zig sources often contains unit tests. You can rely on these and they give you a quick and meaningful way to use some feature.
The language can feel too simple.
Consider this: there is no direct support for classes; indeed OOP is not the only truth, don’t forget about Data Oriented Design or the Zig version).
Let’s try it
I don’t have a fancy ritual to share while picking a new programming language. I do something like this:
- Try to grasp the idea of the language (Which problem does it solve?): Read the home page
- Have a glance at the syntax
- Scroll through the documentation
- Browse randomly its standard library
- Follow some tutorials
- Begin writing trivial programs (let’s say “Guess the number”)
- Write a bit more complex program (for instance a chess or a tower defense I’m both not proud about)
- Start a nice but not too hard-core project, let’s say a Game Boy emulator, how hard can it be?
Bonus
- The Zig Software Foundation is a non-profit corporation (read: more resilience to entshitification).
- The sources are under the permissive MIT license.
- The core team switched to Codeberg over github
- Strict no LLM policy (a really hard-core one, including translation)
- The Zig Software Foundation supports FOSS projects they rely on (musl for instance)
$ zig zen
* Communicate intent precisely.
* Edge cases matter.
* Favor reading code over writing code.
* There is an idiomatic way to do it.
* Runtime crashes are better than bugs.
* Compile errors are better than runtime crashes.
* Incremental improvements.
* Avoid local maximums.
* Reduce the amount one must remember.
* Focus on logic, not style.
* Resource allocation may fail.
* Resource deallocation must succeed.
Together, we serve the users!
Notes
I like to troll (if possible Windows, but apparently there’s not too much left of it to troll), but I don’t really like flame wars.
If you absolutely want a A Vs B programming language topic, do not consider Rust Vs Zig but maybe more Rust Vs C++ and Zig Vs C.