Just to start some discussion about the actual API and not the breaking change aspect of it:
I find the `Reader.stream(writer, limit)` and `Reader.streamRemaining(writer)` functions to be especially elegant to build a push-based data transformation pipeline (like GREP or compression/encryption). You just implement a Writer interface for your state machine and dump the output into another Writer and you don't have to care about how the bytes come and how they leave (be it a socket or shared memory or file) -- you just set the buffer sizes (which you can even set to zero as I gather!)
`Writer.sendFile()` is also nice, I don't know of any other stream abstraction that provides this primitive in the "generic interface", you usually have to downcast the stream to a "FileStream" and work on the file descriptor directly.
As a hobby Zig developer, it's a bummer to see a breaking change in something so fundamental, but I get that's what I accept when building on a pre-1.0 language.
I hope that the Zig team invests more into helping with migration than they have in the past. My experience for past breaking changes is that downstream developers got left in the cold without clear guidance about how to fix breaking changes.
In Zig 0.12.0 (released just a year ago), there were a lot of breaking changes to the build system that the release notes didn't explain at all. To see what I mean, look at the changes I had to make[0] in a Zig 0.11.0 project and then search the release notes[1] for guidance on those changes. Most of the breaking changes aren't even mentioned, much less explained how to migrate from 0.11.0 to 0.12.0.
>Some of you may die, but that is a sacrifice I am willing to make.
>-Lord Farquaad
[0] https://github.com/mtlynch/zenith/pull/90/files#diff-f87bb35...
For context this was presented, alongside other things, in the Zig Roadmap 2026 stream.
something that I don't understand about the actual API:
I maintain the zigler library, and one thing that was useful about the old async "colored-but-not-really" functions was that they implicitly tolerate having internal suspend points (detail: https://www.youtube.com/watch?v=lDfjdGva3NE&t=1819s) -- I'm not sure if having IO be a passed parameter will still let me do that? Can users build their own functions with yield points? And will you be able to jump out of the frame of a function and give control back to the executor, to let it resume later?
A big change like this makes me hopeful Zig may revisit and improve other design choices in the future.
Zig Roadmap 2026 : https://www.youtube.com/watch?v=x3hOiOcbgeA
As someone zig-curious who has to jump around between ruby and elixir, if there’s a nice linting tool that can notify and maybe auto-correct, then I don’t see this as an issue
One issue I have with the old reader/writer pattern is that it is not easy to store them in a struct. Reader and writer are passed into a function as 'anytype' which implements any of the read() or write() functions. Often time in a struct's init() function, I want to take in a reader/writer and store it for later use. It's close to impossible since I don't know what type of the field of the struct to store them.
Does the new change make it easier to store reader/writer in a struct?
By the title I thought that they were going to implement this,
This is why it's good to have automated tooling that can do semantic changes on your language and standard library use. Go has `go fix` even if it was only used in pre-1.0 days AFAIK. It is never lost because this type of tooling can be used as the foundation for linters, refactoring tools, etc. Is there such a solution in Zig?
Is Writergate a technical term or a reference to Watergate?
I tried Zig some time ago to use with microcontrollers. It has a generator for the pins, which was nice. But subsequent versions broke as Zig changed syntax. So I started going down the rabbit-hole (it needed a newer version of llvm, for example) until I eventually decided that the game wasn't worth the candle.
The fact that another breaking change has been introduced confirms my suspicion that Zig is not ready for primetime.
My conclusion is to just use C. For low-level programming it's very hard to improve on C. There is not likely to be any killer feature that some other contender will allow you to write the same code in a fifth of the lines nor make the code any more understandable.
Yes, C may have its quirky behaviour that people gnash their teeth over. But ultimately, it's not that bad.
If you want to use a better C, use C++. C++ is perfectly fine for using with microcontrollers, for example. Now get back to work!
What if you want unbuffered IO?
I have written very little Zig and a lot of Rust, but I love both languages. However, Zig having breaking changes has made me wary of not starting anything serious it with – yet. I'm still happy that these changes happen, because I'm willing to wait for a stable version. Meanwhile, I enjoy myself some Rust, and probably continue doing so.
Well it's about time.
I don't mind breaking changes if I can fix them within a day.
What bothers me with C/C++ is how difficult it is to cross compile a simple Windows + SDL app from inside WSL without MSVC installed.
I've spent weeks on this.
If Zig saves me from that nightmare, and still lets me use C++ libraries, I will gladly switch over to it.
I like Zig but it seems to just keep redesigning itself, while other languages like Odin “shipped” long ago and don’t seem to need to look back. Is Zig suffering from perfectionism syndrome where things are never good enough??
And this is exactly why you do not use shiny new languages for your projects. Hope tigerbeetle won't have too much trouble with this
At my first job, the senior guy on my team used to say:
"Software is just like lasagna. It has many layers, and it tastes best after you let it sit for a while".
I still follow this principle years down the line and avoid introducing shiny new things on my projects.
This arguably is why julia still has no real users and python, c++, and fortran still rule in hpc, despite hypsters doing the hyping.
At some point people just want their code to work so they go back to something that just works and won't break in a few years.
[flagged]
Every time I touched Zig, examples I found on the internet were no longer working. I worked on a project for a while and then the stuff I used was deprecated / broken on the newer version.
I like Zig, but I'm waiting for it to become somewhat stable, because the amount of breaking changes feels pretty significant. I suppose that's the price of progress.
It deeply bothers me that the zig team/community has been aggressively marketing this language while constantly making breaking changes without even providing migration tools. This is user hostile behavior. They are creating extra work for downstream users with minimal gain.
Let's take this change as an example. If I already wrote a program that used the old apis and meets my needs what is the benefit of this change for me? Now I have to go back and rewrite my old code and I might introduce a new bug in the migration, especially if I don't understand all of the nuance in the difference between the apis. Even if I agree that the new apis are better, the cost of migration might outweigh the benefits, but I am forced in to the migration or forking the compiler, which both might be bad choices for me.
It is not necessary to do this. They could, for example, have versioned stdlib and then maybe all I need to is pin my stdlib version. One complaint is that having multiple standard libraries causes more maintenance burden, but why should that be the primary concern? What is the cost to the maintainer vs. the cost to the community. If you make 1000 users spend an hour migrating their code, are you really going to save 1000 hours of maintenance burden?
Moreover, if the zig team wrote code with the assumption that they can never get rid of it, perhaps they wouldn't make so many design mistakes that all of these breaking changes become inevitable.
If I wrote a program in zig, I would feel obligated to also learn how to bootstrap it so that I wouldn't be subject to unwanted breaking changes. But then I see that bootstrapping involves some bizarre wasm hack instead of the tried and true bootstrapping approach of writing a simple first pass compiler in c (or some other language) and I am reminded again why I would never choose this language.
I maintain a library to interface zig with elixir and the breaking changes have not been a big deal. As a part of the library I have maintain a zig parser (the official parser in the langref is not up to date) and I scan the entire zig codebase against my parser to make sure it doesn't trip up on anything. Also I can't use zig fmt to keep up because some of the code is templated and embedded in Elixir. The last two semver minor updates, the net total amount of changes I have had to do to keep up with the language took me maybe an hour? Also subjectively, I feel like the breaking changes that affect me have been fewer and easier to deal with since the early days. The bulk of the delay in updating the library was chipping away at things that i had put off since the last update (also i don't use the library in $DAYJOB since I "quit tech", though I do vibecode solutions for myself).
Point being, I feel like a lot of the gripes about zig changing here and there are really by folks who aren't really daily users, just people who see a !!breaking change!! announcement and pile on.
Though, I do sympathize with newcomers because the memory of the internet is pinned to various older versions with lots of demo code that 'just doesn't work' and of course that means LLMs too, in the long run. Hopefully zig doesn't get stuck past the global knowledge/popularity LLM-cycle cutoff. I don't think it will.