I’ve read that some well known projects written in Zig have been described as examples of how not to write Zig.
What open source projects would you consider to have state of the art Zig code and be good examples to learn from?
I’ve read that some well known projects written in Zig have been described as examples of how not to write Zig.
What open source projects would you consider to have state of the art Zig code and be good examples to learn from?
I propose my project - tofu
Next zig dev will propose theirs.
But will have to explain why it’s better.
After several iteration you will get the picture
Short list please
Kind of an obvious answer, but I will mention it anyways:
The Zig compiler and standard library.
The standard library is relatively easy to read (unless you need to dig into the IO vtable) and contains several useful patterns.
The compiler can help you discover how to design and structure an application, and by necessity it’s also the most up to date Zig project you will find.
I really don’t think any answer is going to be better than this.
It is also always available, and only a click/keystroke away with an LSP. I have learned a lot of useful patterns throughout my Zig journey this way without even intending to, just throughout the course of writing my own code and inspecting a stdlib type to get a better understanding of what a function did, etc.
Unlike C, you won’t be chasing down macros that use other macros which expand into blocks of code written by some wizard in the 70’s who refused to name a variable using more than 1 character.
Thanks everyone, this is already a great starting point.
If you had to review a Zig project today, what would make you say “this is excellent Zig code” rather than “this is just working code”?
I’m trying to build an intuition for what experienced Zig developers consider idiomatic.
I also use Ghostty as my daily terminal and follow Mitchell’s work.
I’ve already started digging through the code a bit, but it’s a fairly large project, so I’m taking it one piece at a time.
I’m currently building a terminal UI application myself, and I was particularly curious about how Ghostty handles rendering and terminal interactions.
While this topic doesn’t explicitly ask for this, it still seems like a relevant/related question:
What are commonly occurring patterns/problems/solutions in Zig code?
Here are some patterns @tensorush has collected:
And there are also a bunch of discussions around specific problems and how to best solve them scattered around this forum.
I still haven’t looked at TigerBeetle’s code in enough detail, but from their talks and blog posts they have published, they have implemented a lot of good ideas around design, reliability, testing, simulation-testing, fuzzing, etc..
That’s a big question, and one I think the community is still trying to work out to some extent.
A few things come to mind though.
Zig is written to make data-orientated-design straightforward. Object-orientated patterns look ugly, and they’re meant to (to some degree). The language is trying to tell you to leave them behind.
Dependency injection to keep code reusable, be it Io, or Allocator, or whatever else. It helps testing, and it means you can use code between projects that might have different context going on.
Fairly few layers of abstraction. We program computers and that means getting the CPU to do what you tell it. It doesn’t mean installing a library to left-pad a string. That doesn’t mean you reinvent the wheel, but if you have dependencies they’re going to be specific.
Judicious use of comptime to reduce work at run-time. I really like the standard library string formatter as an example of this. The format string is used to generate a function, and that function prints out those variables in that format. Every other language I know interprets the format string at run-time. Why? It’s constant.
Well to be fair, for string formats that are almost never used that would also be a nice option to have, to save on code size. I think here it could be cool to have something like profile guided optimization and then the compiler could pack all the very rare format strings into a method that does runtime interpreting for those only.