This feels like it should've been a git issue rather than a blog post.
No feedback from the author, no explaining what the code does at a level for people new to zig, no explanations of the fundamental problem (i.e. files, buffers, and flow of data, and how to write that as code) and how it relates to what zig is doing, no alternate solution for how zig or other languages might try to solve the problem.
I have a strong suspicion that people are upvoting this based on the title of 'Zig' and 'unsafe' instead of the actual substance of the post.
I've never worked with Zig in my life, and I don't have an opinion on it either. I've heard it's neat. Despite that, this post was intuitively clear to me.
Zig's *std.Io.Reader and Writer seem to be abstractions over many types, like Java's interface class, Go's interfaces, C++'s concepts or Rust's traits.
However, it seems that abstraction itself is leaky - in that the length of the buffer is an implicit dependency which cannot be known from the type alone.
Admittedly, we don't know if there's a good explanation for the behavior - but then again, HN comments are as good a place to learn as any. Maybe someone will come up and explain.
What a terrible way to take constructive feedback.
Writing not one but two blog posts takes time and effort, moreso when it includes investigation and examples... the posts are not just low effort "this is crap" rants (and they even blame themselves, even though it's clear from the posts that there are documentation/discoverability issues).
What if the poster doesn't feel knowledgeable enough to contribute code? (as shown by his first post title, "I'm too dumb for...")
If that's not collaborating I don't know what it is...
> Kinda wish the author would attempt to collaborate rather than write stuff like this and I’m too dumb for Zig’s new IO interface but, whatever, it’s their blog so they can do what they want.
Damn, Andrew Kelley really come across as a dickhead when taking any bit of criticism about his language, often painting them as bad actors trying to sabotage the language.
This isn't the first time he repeats this behavior.
Like a modern C with lessons learned. Instead of macros it uses Zig itself to execute code at runtime (comptime). Custom allocators are the norm. No hidden control flow, everything is very explicit and easy to follow.
But it’s not only the language itself, it is also the tooling around it. Single unit of compilation has some nice properties, allowing to support colorless async. Fast compile times. Being able to use existing C code easily and having optimization across language boundaries. Cross compilation out of the box. Generally caring for performance in all aspects.
So for me it is a better C, low-level but still approachable and not having so much cruft.
The value proposition of Zig is it's the most ergonomic way to do systems programming I've ever seen. First class allocators, arbitrary width integer types, top notch bindings to OS syscalls in the std lib without relying on libc, and you can translate C bindings to Zig at compile time, so no FFI layers for existing libraries.
They sometimes write about how they're a general purpose language, but I strongly disagree. It's unapologetically a systems programming language; that's it's entire focus.
Zig’s undefined behavior story is not nearly as much of a minefield for one. That should be enough really. If you think the CPP is good enough for metaprogramming, I don’t know what to tell you either.
It's a language that attempts to solve more of the biggest issues with low level programming than any other current low-level programming language. Of course, there is nowhere near a universal consensus on what the biggest issues are, but here's what they are to me in order of importance (and I'm not alone):
1. Language complexity/lack of expressivity. You want code, as much as possible, to clearly express the algorithm at the level of detail needed at the language's domain, no more and no less. The level of detail in low-level languages is different from high-level languages because, for example, you want to see exactly where and when memory is allocated/freed. Both C and C++ fail at this for opposite reasons. C is often not expressive enough to express an algorithm clearly (at least not without the use of macros), and C++ is often too implicit, hiding important details that are then easy to miss [1]. These problems may affect program correctness.
2. Lack of spatial memory safety, which is the cause of the #2 and #6 most dangerous software weaknesses (https://cwe.mitre.org/top25/archive/2024/2024_cwe_top25.html). Unlike spatial memory safety, Zig doesn't guarantee the lack of temporal memory safety. This would have been very nice to have, but it isn't as important and not worth compromising on the other top points.
3. Slow build times, which may also affect correctness by slowing down the test cycle.
I don't find Zig similar to C or C++ at all (certainly not as similar as Rust is to C++). If anything, Zig's risk is in being a more revolutionary step than an evolutionary one.
---
[1]: In the late eighties/early nineties (when I first learned C++), when we thought it might be a good idea for a language to be both low-level and high-level, C++'s notion of "zero-cost abstractions" seemed very interesting and even promising (I don't recall them being given that name then, but the problem - or advantage - was right there at the beginning; e.g. whether a call uses static or dynamic dispatch is an algorithmic detail that may be of interest in low-level programming, as well as whether a destructor is called, possibly through dynamic dispatch). Now that notion feels an outdated vestige of a bygone era. I'm aware there are still C++ programmers who still believe in writing high level applications in low-level languages and still believe in zero cost abstractions, but I think the industry has clearly been going the other way, and there's no indication it may be changing direction or may have any reason to do so.
It's a powerful alternative to Rust and C++ for writing ultra low latency code when safety isn't important, like games or HFT. Its standard library and ecosystem have excellent support for passing around allocators and no hidden dynamic allocation (every function that allocates takes an allocator as a parameter), which makes it much harder to hit the latency pitfalls common to Rust and C++. It also encourages the latency-optimal approach of using local bump-a-pointer arena allocators where possible rather than the slow global allocator. And finally, the superior metaprogramming support makes it more convenient to use high performance techniques like struct-of-arrays.
Zig's pointless choice to avoid global constructors - something all platforms have supported for several decades by now - makes I/O extremely unwieldy. That alone prevents it from being a viable mainstream language.
There is a lot of useful technical work and ideas in it though.
Being the anti Rust alternative for people who has spent years/decades accumulating weird knowledge about the inner workings of C and/or C++ and maintain that being able to shoot your feet off at a distance when doing the wrong incantation is a critical feature to have.
I’m ranting but based the Rust/Zig discussions here on HN and the number of segfault issues in the Bun repo there is a core of truth.
[+] [-] preommr|6 months ago|reply
No feedback from the author, no explaining what the code does at a level for people new to zig, no explanations of the fundamental problem (i.e. files, buffers, and flow of data, and how to write that as code) and how it relates to what zig is doing, no alternate solution for how zig or other languages might try to solve the problem.
I have a strong suspicion that people are upvoting this based on the title of 'Zig' and 'unsafe' instead of the actual substance of the post.
[+] [-] bheadmaster|6 months ago|reply
Zig's *std.Io.Reader and Writer seem to be abstractions over many types, like Java's interface class, Go's interfaces, C++'s concepts or Rust's traits. However, it seems that abstraction itself is leaky - in that the length of the buffer is an implicit dependency which cannot be known from the type alone.
Admittedly, we don't know if there's a good explanation for the behavior - but then again, HN comments are as good a place to learn as any. Maybe someone will come up and explain.
[+] [-] paulddraper|6 months ago|reply
[+] [-] tialaramex|6 months ago|reply
[+] [-] jmull|6 months ago|reply
[+] [-] latch|6 months ago|reply
[+] [-] simjnd|6 months ago|reply
https://lobste.rs/s/js25k9/is_zig_s_new_writer_unsafe#c_ftgc...
[+] [-] wolvesechoes|6 months ago|reply
[+] [-] kaoD|6 months ago|reply
Writing not one but two blog posts takes time and effort, moreso when it includes investigation and examples... the posts are not just low effort "this is crap" rants (and they even blame themselves, even though it's clear from the posts that there are documentation/discoverability issues).
What if the poster doesn't feel knowledgeable enough to contribute code? (as shown by his first post title, "I'm too dumb for...")
If that's not collaborating I don't know what it is...
[+] [-] flykespice|6 months ago|reply
Damn, Andrew Kelley really come across as a dickhead when taking any bit of criticism about his language, often painting them as bad actors trying to sabotage the language.
This isn't the first time he repeats this behavior.
EDIT: https://news.ycombinator.com/context?id=45119964 https://news.ycombinator.com/context?id=43579569
[+] [-] didibus|6 months ago|reply
What's the value proposition of Zig? It's not immediately obvious to me.
Is it kind of like the Kotlin of C, going for a better syntax/modern features but otherwise being very similar?
[+] [-] ManBeardPc|6 months ago|reply
But it’s not only the language itself, it is also the tooling around it. Single unit of compilation has some nice properties, allowing to support colorless async. Fast compile times. Being able to use existing C code easily and having optimization across language boundaries. Cross compilation out of the box. Generally caring for performance in all aspects.
So for me it is a better C, low-level but still approachable and not having so much cruft.
[+] [-] bmacho|6 months ago|reply
[+] [-] LAC-Tech|6 months ago|reply
They sometimes write about how they're a general purpose language, but I strongly disagree. It's unapologetically a systems programming language; that's it's entire focus.
[+] [-] epcoa|6 months ago|reply
[+] [-] pron|6 months ago|reply
1. Language complexity/lack of expressivity. You want code, as much as possible, to clearly express the algorithm at the level of detail needed at the language's domain, no more and no less. The level of detail in low-level languages is different from high-level languages because, for example, you want to see exactly where and when memory is allocated/freed. Both C and C++ fail at this for opposite reasons. C is often not expressive enough to express an algorithm clearly (at least not without the use of macros), and C++ is often too implicit, hiding important details that are then easy to miss [1]. These problems may affect program correctness.
2. Lack of spatial memory safety, which is the cause of the #2 and #6 most dangerous software weaknesses (https://cwe.mitre.org/top25/archive/2024/2024_cwe_top25.html). Unlike spatial memory safety, Zig doesn't guarantee the lack of temporal memory safety. This would have been very nice to have, but it isn't as important and not worth compromising on the other top points.
3. Slow build times, which may also affect correctness by slowing down the test cycle.
I don't find Zig similar to C or C++ at all (certainly not as similar as Rust is to C++). If anything, Zig's risk is in being a more revolutionary step than an evolutionary one.
---
[1]: In the late eighties/early nineties (when I first learned C++), when we thought it might be a good idea for a language to be both low-level and high-level, C++'s notion of "zero-cost abstractions" seemed very interesting and even promising (I don't recall them being given that name then, but the problem - or advantage - was right there at the beginning; e.g. whether a call uses static or dynamic dispatch is an algorithmic detail that may be of interest in low-level programming, as well as whether a destructor is called, possibly through dynamic dispatch). Now that notion feels an outdated vestige of a bygone era. I'm aware there are still C++ programmers who still believe in writing high level applications in low-level languages and still believe in zero cost abstractions, but I think the industry has clearly been going the other way, and there's no indication it may be changing direction or may have any reason to do so.
[+] [-] Cloudef|6 months ago|reply
[+] [-] giancarlostoro|6 months ago|reply
I am not a C++ guy, but when Carbon is finally stable and hits the mainstream, I will definitely start trying out Carbon.
https://github.com/carbon-language/carbon-lang
[+] [-] Galanwe|6 months ago|reply
There's not much languages in that space, essentially C3 and Zig, but the former is much less advanced IMHO (also in terms of tooling).
[+] [-] pjmlp|6 months ago|reply
It is the route of what would have happened if Modula-2 or Object Pascal had won the industry mindshare instead of C.
I think it comes too late, we know better nowadays, so it doesn't really offer anything new.
[+] [-] logicchains|6 months ago|reply
[+] [-] tliltocatl|6 months ago|reply
For me that sounds like a rather good value proposition. Too bad Zig never got the stackless corountine part they promised in the start.
[+] [-] epolanski|6 months ago|reply
[+] [-] o11c|6 months ago|reply
There is a lot of useful technical work and ideas in it though.
[+] [-] ViewTrick1002|6 months ago|reply
I’m ranting but based the Rust/Zig discussions here on HN and the number of segfault issues in the Bun repo there is a core of truth.
https://github.com/oven-sh/bun/issues?q=Segfault
[+] [-] casey2|6 months ago|reply
[+] [-] hu3|6 months ago|reply