back
180 comments
I have admired many parts of Zig and its philosophy but I've never seen it as a language that I want to use. What I've noticed is that Zig users care most about explicitness, simplicity, and minimal indirection. This leads to a lot of syntax that is cumbersome to read (albeit unambiguous) like casting and a lack of "convenience" features. I can't help but think that maybe they're right and that this philosophy probably leads to better software because nothing is "hidden". But, I also think that there's a level of abstraction/indirection that makes code clearer and less error-prone. It's a tricky balance to achieve, and past languages have succeeded and failed at it to different degrees. Either way, I echo the OP's sentiment: if Zig is your jam, great, go make some awesome stuff with it. It's just not my go-to today.
Design choices that are appropriate for low-level programming may be less appropriate for high-level programming and vice versa. In low level programming, you may want to see "on the page" anything that could translate to some machine work, because in low-level programming, such details may be essential to the algorithm. In high-level programming, the same details are likely not essential to the algorithm, and so you don't want to see them.
I think, but I may be wrong, Zig wants to be high level assembly that could replace C. If people are viewing it from Python, Ruby, JS, and then C++ and Java POV, Zig may be a little too "raw". But then I don't think Zig intends to compete with C++ or Java. May be there will be a Zig ++ or Objective-Zig someday that will do that.
It really comes down to a matter of opinion where the line between "nothing hidden" and convenience lies. Technically, a loop is an abstraction of convenience that hides the comparative jump underneath.
> Zig's comptime is a very large and all-encompassing feature that ultimately brings very little to the table that smaller features cannot.

> I am personally a proponent of a good macro system.

Comptime is much more constraint than any macro system: no code generation (including AST rewrite), no arbitrary tokens. Thus it's much harder to "go overboard" with Zig's comptime. This constraints of cource have their drawbacks, but code generation is still a thing.

> Much of Zig seems to me like "wishful thinking"; if every programmer was 150% smarter and more capable, perhaps it would work.

Nice way to put it! But I oppositely believe the world needs more tech that treats professionals as experts, not kids.

> Nice way to put it! But I oppositely believe the world needs more tech that treats professionals as experts, not kids.

That’s how it was until around the turn of the century. Who needs types, we’re adults after all. Memory safety and garbage collection? Oh please go back to kindergarten.

But then some of us learned that no matter how smart we are, we can make mistakes that those things can actually prevent. And those mistakes can have catastrophic consequences. Professionals should go for tools that help them prevent those mistakes, right??

> But I oppositely believe the world needs more tech that treats professionals as experts, not kids.

Which part of expertise is rejecting the fact that safety through professional mind tricks in lieu of better underlying language design is unattainable?

> But I oppositely believe the world needs more tech that treats professionals as experts, not kids.

This made me think about Rust borrow checker: given the amount of people struggling with it, I would think the number of experts is much lower than I would initially assume.

> But I oppositely believe the world needs more tech that treats professionals as experts, not kids.

Seconded. I've really come to loathe tech that is constantly trying to "help me" unprompted and do things I didn't ask/want it to do or burying settings/configurations if not obfuscating them away entirely and acting as if it's doing me a favor by removing features in the name of "simplicity" or some shit. And let's not forget built-in obsolescence moonlighting with privacy-disrespecting dark patterns masquerading together as "Smart Devices."

> But I oppositely believe the world needs more tech that treats professionals as experts, not kids.

This attitude is why we still have bounds checking memory bugs in new software in 2025.

IMHO an artisan should want superior tools that produce better results.

Not an expert, but isn't Zig's comptime essentially an AST generator?
>> Much of Zig seems to me like "wishful thinking"; if every programmer was 150% smarter and more capable, perhaps it would work.

... and the same could be said about Rust, only with Rust we can already see that it suffers from relatively low adoption at a relatively advanced age.

The funny thing about that claim is that it leads to an obvious question: if working harder to satisfy the compiler is something that requires less competence than other forms of thinking about a program, then why Rust? Why not ATS? After all, Rust does let you eliminate certain bugs at compile time, but ATS lets you eliminate so many more.

I find a lot of these points persuasive (and I’m a big Rust fan so I haven’t spent much time with Zig myself because of the memory safety point), but I’m a little skeptical about the bug report analysis. I could buy the argument that Zig is more likely to lead to crashy code, but the numbers presented don’t account for the possibility that the relative proportions of bug “flavors” might shift as a project matures. I’d be more persuaded on the reliability point if it were comparing the “crash density” of bug reports at comparable points in those project’s lifetimes.

For example, it would be interesting to compare how many Rust bugs mentioned crashes back when there were only 13k bugs reported, and the same for the JS VM comparison. Don’t get me wrong, as a Rust zealot I have my biases and still expect a memory safe implementation to be less crashy, but I’d be much happier concluding that based on stronger data and analysis.

I had the same thought. But one thing was actually very useful to compare "bug densities": deno vs bun. They have comparable codebase sizes as well as comparable ages (7y vs 4y). I'd like to see the same stats for tigerbeetle, which is very carefully designed: if segfaults were relatively high on that as too, well...
> Don’t get me wrong, as a Rust zealot I have my biases and still expect a memory safe implementation to be less crashy

That is a bias. You want all your "memory safety" to be guaranteed at compile time. Zig is willing to move some of that "memory safety" to run time.

Those choices involve tradeoffs. Runtime checks make Zig programs more "crashy", but the language is much smaller, the compiler is vastly faster, "debug" code isn't glacially slow, and programs can be compiled even if they might have an error.

My personal take is that if I need more abstraction than Zig, I need something with managed memory--not Rust or C++. But, that is also a bias.

The authors section on comptime makes me believe they have not used zig anything non trivial.

I don’t think comptime as just some macro system. It is closer to a reflection system. I use comptime to access types. You can create specialized paths depending on type.

Also imo generics are “first class” in zig. Comptime is first class and thus generics are too.

> X is first class and thus Y [implemented in terms of X] is too.

Is everything first class, then?

I find the point about memory safety to be pretty damning.

People think it's a slight on their abilities. "I can write memory safe code!" Maybe you can. There are two huge problems here, and they're problems that will never go away no matter how good you are.

The first is that this doesn't scale. As soon as you add more programmers to a project, you multiply the odds of bugs like this. Even if everyone's just as good, not everyone will have the whole program in their head or code in exactly the same style.

The second is that code rots. Your new C (or Zig) program might be totally correct and memory safe when it's first written. Then you commit it to a repo. Then you move on to another project for a while. Then someone else fixes something and you merge a PR. Then you come back to it three months later and you're under pressure to implement something. Then you work in a new feature a year later and you've forgotten some of the really nit-picky details of how things work. It's very easy over time for bugs to creep in, and if the language doesn't catch them they'll sit in the code until they cause random crashes or, worse, a CVE.

These aren't avoidable issues. They're inherent to software and its life cycle. Memory safe languages (and secure computing systems in general) are the only way to deal with them.

Why have I been seeing a Zig post every day for the past week? Is there some kind of a marketing push?
Interest on various topics comes in waves on HN. This week it's Zig, next week it's Scheme, the week after is Erlang, etc. Nothing out of the ordinary.
I think there's a small trend upwards for Zig & Nim right now. I've seen a few different front page posts for them in the last couple weeks. It at least convinced me to clone ziglings and get a feel for it this last weekend.
There's bursts of them and every 3-6 months I see one like this, more practical, and remember I don't need to read the others. Then I forget in 3 months. Rinse, lather, repeat. (to this 16 year veteran of HN, it reminds of early 2010s Haskell)
It may be due to the async/io changes which may have caused a wave of renewed interest in the language
Advent of code is coming, maybe lots of people looking for a language to learn with it?
still less than Rust posts.
What about more people using it? More than anything this looks to be natural evolution of language.
The author refers to casting ints to floats but seems to actually be talking about converting. Casting is when you change the type, but don't change the data..

I don't really think much of Zig myself for other reasons, but comptime seems like a good design.

> Casting is when you change the type, but don't change the data..

Is that the case? That's not what I think of when I think of C-style casts.

    float val = 12.4;
    int val_i = (int) val;
The representation in memory of `val` should not match that of `val_i`, right? The value is encoded differently and the quantity is not preserved through this transformation. I don't think that means that the data weren't changed.

Maybe you're thinking of aliasing/type-punning? Casts in C do perform conversions as they do in C++.

Casting and type conversion are synonyms: https://en.wikipedia.org/wiki/Type_conversion
probably should define memory safety before using it as an evaluation criterion

otherwise, not sure who the audience of this piece is supposed to be, but it's written in a pretty combative tone, which will not be persuasive to anyone who isn't already persuaded, so i guess more of a rant than anything worth sharing here

I can see where you're coming from, but I do think there's a fair amount of meat here. I've never used Zig, but I initially thought of it as pretty similar to other modern languages like Go and Rust, and I liked their allocator approach, but the post gives compelling statistics (Bun has almost EIGHT times as many crash issues as Deno over a similar number of tickets) on Zig's memory safety approach and its issues that also line up with my experience. I used Bun for a small data-collection project, and I liked its performance, but I ran into a lot of issues with it segfaulting (even when just passing a command line argument that was added in the most recent version!). I think that does a good job of motivating OP's argument and how Zig's language semantics directly contribute to these issues.
Someone could know what memory safety is and still be persuaded (or reminded) by an argument that it's not okay to adopt a non-memory-safe language due to all the security issues. The author did cite evidence from the Chromium project, which to me elevates it above a mere rant.
> One extra register is all you ever need, even for an arbitrary parallel move!

This statement, albeit true, is highly misleading. In the example given, you ought to be concerned with parallel assignments not parallel moves. See [0] for more details on the distinction.

[0] https://inria.hal.science/inria-00289709

What’s the opposite of damning with faint praise? “Removes many but not all of the C footguns. Self hosted compiler isn’t that much faster than Clang.”
> The Zig compiler is not particularly fast.

This really makes me question the accuracy of the rest of the article.

I'm really struggling to come up with a compiler that is faster than Zig.

Go, maybe? That's ... about the end of my shortlist.

Lauding with faint blame ? :)
It's interesting to see how popular Zig is becoming, I thought it would get overshadowed by Rust and it would go nowhere.
It's interesting how much Rust has slowed down. There is still some development in linux otherwise people seem to be over it. I think Rust just doesn't offer enough in terms of features, and is overshadowed by languages like Go or C++ in terms of what developers are really looking for. Rust's popularity seems to be dropping or holding steady in indexes like TIOBE, and a lot of big "influencers" seem to be over Rust's hype cycle
But they are not even competitors.

Zig is a better C. No abstractions. Close to bare metal.

Rust is a better C++. Abstractions to simplify application level programming.

This article works really well to illustrate a question I have: why is Zig so popular in posts here?

For most languages I can usually see one or two “killer features” that push the language: For Rust is taking C space with memory safety + modern semantics, for Go is being easy to learn by most engineers + parallelization, for Ruby is ergonomics…

I don’t see any similar pitch for zig other than a general “I kinda enjoy it”, and the language seems to have a couple red flags, so why focus on it? (Honest question).

> for Ruby is ergonomics…

My impression is that this is the main thing for Zig too. The intersection of the set of languages that let you write very low-level code where you have full control over memory and allocation and the set of languages that are enjoyable to program in is pretty small.

C is in there if you've internalized many of its warts are fine with all of the many many footguns it has. C++ is in there if you much of your enjoyment comes from the machismo of feeling like you have conquered C++'s beastly language complexity. Rust is in there if proving to the compiler that you know what you're doing is satisfying to you.

Zig sort of gets out of your way like C does, even when what you're trying to do is potentially harmful. But it's more modern and expressive and doesn't have all of C's historical baggage.

Turns out that "killer features" are frequently not killer enough. You mentioned Rust with its memory-safety killer-feature, and yet Rust is quite old now (about as old as Java was when JDK 6 came out or JS was when jQuery came out) and its adoption rate is low for such an old age.

I have no idea if Zig will be successful or not, but even if you look just at memory safety, I think it does a better job at that than Rust. If you look at MITRE's top 25 dangerous weaknesses [1] or top 10 exploited weaknesses [2], you'll see that Rust spends almost all of its complexity on eliminating weaknesses that don't even make the top 5 on either list, while Zig's more limited memory safety addresses the more dangerous memory-safety-related problems without paying so dearly to solve less severe issues.

Now, I personally think that Zig's combination of expressivity and simplicity, while still being low-level, is an unprecedented killer feature (I wrote more about it here: https://news.ycombinator.com/item?id=45852774) which makes the language design quite revolutionary and fascinating. This could perhaps translate to correctness benefits.

[1]: https://cwe.mitre.org/top25/archive/2024/2024_cwe_top25.html

[2]: https://cwe.mitre.org/top25/archive/2024/2024_kev_list.html

For me, personally, it is nice because it's bare metal where I want it and not bare metal when I don't.

C is very basic and (especially when you stick to something like C99), can be very tedious to write. In C, if I hope for smarter things I need to write them by hand; usually there are no ways of achieving some goals without just crunching out the code. Zig preserves C qualities but also gives some extra tools that are completely optional and makes it less tedious than C.

I believe that Zig's popularity is also caused by general tendency of some people. Some prefer to fix a segfault than spend half a day refactoring something that was supposed to be easy but is causing half of the codebase to be rewritten.

(Oh, and Zig is also an escape hatch to easy CGo :))

I think the post gives an answer to this with "due to Zig's fairly minimalistic nature; it lacks a lot of features that one would otherwise use to solve problems. Of course, this is the appeal for many, but still". I have a lot of C/C++ experience, and they're what I reach for, but I often want C to be a little more like C++, and I often want both to have slightly better memory management, and I've never liked the different syntax for the main language, templates, and pre compiler macros. I also agree with Zig's dogmatic stance on no hidden control flow; I have been bitten by "magic" too many times.
Some people like Zig because it makes it easier to learn how to program the machine sitting in front of them.

It's better at that than Rust because it's less abstracted, and it's better at that than C because you don't have to worry all the toolchain nonsense / weird conventions / weak type system of the C ecosystem.

As a small example wrt Rust: resetting an arraylist/vector while reusing its memory is a weirdly complicated trick https://lobste.rs/s/emvkea/why_we_didn_t_rewrite_our_feed_ha...

I think I don't need to provide references for C.

It's a new pathway to mastery that really works well for some people. That in itself is much more valuable than any new specific feature the language has to offer, although the ability of the toolchain to cross-compile reliably not only Zig but also C and C++ code does play into that.

And, while not yet 100% there, instant incremental rebuilds also help to achieve faster feedback loops.

People like Zig because it's a tool that helps them become better programmers, faster.

> Zig does not have a way to iterate through a slice or similar in any way except one-at-a-time forwards. Anything else? You're using a while loop, and you'll enjoy it.

    INCR[U] i FROM 0 TO len(arr) [BY 1] DO ...

    DECR[U] i FROM len(arr) TO 0 [BY 1] DO ...
Although actual BLISS-77 had inclusive semantics for the upper bounds in both forms. Which, on one hand, allows you to write

    DECRU i FROM UINT_MAX TO 0 DO ...
and expect it to Just Work™ (hopefully? No idea if it worked on actual implementation ― but would've been nice, writing the same in e.g. C is kinda annoying; good luck with Golang pre-1.22 and even then, getting that one last iteration is quirky) but on the other hand, inclusive upper bounds require you to write add that "-1" almost everywhere.
This treatment of memory safety is becoming almost a cargo cult at this point. If this were a binary issue, then clearly Rust wouldn't cut it because it is quite common in Rust (much more so than in, say, Java) to rely on unsafe code. So if you think Rust is good at memory safety, that means that you must believe that some level of unsafety is acceptable. The only question is how much, and what you're willing to pay to reduce it.

The reason we care about memory-safety so much, compared to other invariants we'd like our programs to have is because, as the article notes, a very high portion of vulnerabilities are due to memory-safety violations. This is why preventing or reducing such violations is important in the first place.

But if we look at vulnerability rankings [1][2], we see that Zig's memory safety covers the top weaknesses just as well as Rust, and much better than C. The vast difference in the complexity of these two languages is because Rust pays a lot to also prevent less dangerous vulnerabilities, outside the top 5.

So if Rust is good because it eliminates some very common dangerous vulnerabilities thanks to its memory safety, then Zig must also be good for eliminating the same ones. Calling it C-like because it doesn't eliminate some less common/dangerous vulnerabilities just because Rust does, is just a misunderstanding of why this is all important in the first place. (Plus, if it's important to reduce the security vulnerabilities due to memory safety violations, isn't it better to make avoiding the worst outcomes more approachable?)

In software correctness there are few easy choices. Everything boils down to how much you can and should pay to improve your confidence that a certain level of damage won't occur. It's a complicated subject, and trying to present it as a simple one does it a great disservice.

In fact, both Rust and Zig address some of the most common/dangerous vulnerabilities — more than use-after-free - just as well as C, which is to say, not, or barely, at all. I.e. there are worse vulnerabilities that neither one of them eliminates than the ones Rust eliminates and Zig doesn't.

There is no doubt that Rust and Zig are meant to appeal to people with different aesthetic preferences, but the attempt to distinguish them by turning the matter of memory-safety into a binary one simply doesn't make sense. The property of memory safety is itself not binary in both languages, and the impact of memory safety is split between more and less important effects.

I understand why people wish to find objective metrics to prefer one language over another, but often such metrics are hard to come by, and extrapolation based on questionable assumptions is not really objective.

But if you choose to only focus on security weaknesses, and you choose to ignore the language design's impact on code reviews or the fact that allocations are much more visible in Go than in C (which is not very objective, but perhaps you consider these harder to quantify), you would still have to conclude that there's a big difference - on your chosen metric alone - between Zig and C, and a rather small difference between Rust and Zig.

What I think really happens, though, is that most of the preference boils down to aesthetics, and then we desperately seek some objective measures to rationalise it.

> Much of Zig seems to me like "wishful thinking"; if every programmer was 150% smarter and more capable, perhaps it would work.

But if working harder to satisfy the compiler is something that requires less competence than other forms of thinking about a program, then why Rust? Why not ATS? After all, Rust does let you eliminate more bugs at compile time than Zig, but ATS lets you eliminate so many more. So, if this is an objective measure to reject Zig in favour of Rust, then it must also be used to reject Rust in favour of ATS.

Neither Rust nor Zig are anywhere near either extreme on compile-time guarantees in general and memory-safety in particular. They're closer to each other on the spectrum than either one of them is to either C or ATS. They both compromise heavily. It's perfectly fine to prefer one compromise over the other, but to a measure that would settle which of these compromises is objectively better is just not something we have at this time.

[1]: https://cwe.mitre.org/top25/archive/2024/2024_cwe_top25.html

[2]: https://cwe.mitre.org/top25/archive/2024/2024_kev_list.html