No surprises on any system: Q&A with Loris Cro of Zig
With so many languages to program in already, you may wonder why people still create new ones. But on last year’s Developer Survey, a new language called Zig showed up with a small following but the third-highest Admired score. To find out what this new language was about, I reached out to Loris Cro, VP of Community at the Zig Foundation and host of Zig Showtime, to talk about what makes Zig worth checking out.
This conversation has been edited for clarity and content.
Ryan Donovan: How did you get involved in Zig?
Loris Cro: So before this job, I used to work at Redis Labs. I was a developer advocate, so part of my job was to show people how to do stuff with Redis, and I needed a lower level programming language to showcase how to use a specific feature of Redis. Redis has a plugin system, but to write a plugin, like a module, you have to create a dynamic library, which is something that only lower level programming languages can do.
So I tried with C, which was not a good experience, so I looked into newer languages. Of course I saw Rust, but I also saw Zig, and Zig really captured my attention. This is how I first learned about Zig.
I started using it and fast forward a few months, maybe a year, and the pandemic struck. In the meantime, I had gotten more involved with the community. I was running a show on Twitch called ZigShowtime because the idea was that as the pandemic started and the lockdown started, in person events transitioned into online events, except that they were basically becoming like extracurricular meetings. In my opinion, people weren't doing the greatest job at translating, at changing medium.
The idea with Zig Showtime was to make an online meetup, but instead of it being a Zoom call, make it like a livestream show, with an intro, with music, with me acting as a host as if it was a real show. People liked it enough. Around the same time, Andrew Kelly, the creator of Zig, created theZigSoftwareFoundation, like a 501(c)(3) non profit and asked me to join him as VP of Community. So that's how it started.
RD: What captured your attention about Zig?
LC: I think two main things, one technical and one, well, less so. The technical thing that really captured my attention when it comes to Zig was comptime. Zig does metaprogramming, but it doesn't do metaprogramming with macros. Instead, it uses a different system called comptime.
Macros are very powerful, but they are also very brittle because they basically are programs that manipulate the syntax of your source code more or less. As I said, that’s very powerful, but it's also very brittle because you're messing around with text. Things lose some of their semantic meaning and just become tokens.
I like metaprogramming, and I think the macros are horrible. With comptime, what you do is use the language itself to manipulate part of the language in a more semantic way. You treat the language as a data structure, kind of like you do in Lisp, except it's not a Lisp language. There are some significant differences.
The second one was watching Andrew, the creator, interact with people on GitHub. I noticed right away that he had a very effective approach to interacting with contributors and guiding newcomers, making sure that all the interactions end up being productive for both sides. I think this strength is part of the reason why Zig is where it is today, not just the technical reasons.
In the end, what he wanted was something more similar to C, but with the main obvious foot guns solved and improved. That's when he started Zig.
RD: I noticed one of the guiding principles was simplicity, especially in terms of control flow and memory allocation, not having those surprises show up.
LC: Exactly. Because these are the kind of things that if you're not careful about—if we go back to the digital audio workstation example, that's what would make it impossible for you to make a good one.
RD: That seems to make it fast and almost deterministic. Like, you know what's going to happen. There's not going to be any dynamic surprises there.
LC: In my opinion, that's maybe the greatest strength of C. In hindsight, C has a very long list of issues and bad things about it, but it also has a beauty. I think that the main component of C’s beauty is the fact that you can jump into some code and—assuming people didn't go crazy with macros—you can easily tell what's going on.
That’s because people can't overload operators and can't hide memory allocation. Actually with Zig, this is taken to an extreme that even C doesn't do. For example, with C, you have functions that do allocate without necessarily you giving them an allocator, because functions assume that malloc is available in Zig.
This is not the norm. In Zig, every data structure takes in an allocator explicitly. It's even more obvious to understand which parts of your program allocate memory and which ones don't
RD: So if you wanted to specifically allocate and limit memory, if you wanted to have the exact addresses of the memory, you could do that, right?
Loris: Yeah, but even more importantly, I would say that by always having a form of dependency inversion or injection when it comes to our allocators—having the caller specify the allocator—you also gain a lot of usability.
WebAssembly, for example, has strict limits on how memory is supposed to work. All the data structures in the standard library can be used in WebAssembly, no exception, because everything that allocates can accept a WASM allocator when you are targeting WASM.
Similarly, for embedded data structures, you are in a very constrained environment, and you want to use a data structure that has some dynamic behavior in terms of memory allocation, but you don't have a real heap. You can allocate a buffer on the stack and create a stack allocator, which basically uses a chunk of memory from the stack as its quote unquote heap. Then you pass that to other data structures, like hash maps and stuff.
Obviously, there are limits. You're not able to use the data structure with the full flexibility compared to when you have a real 64 gigabyte heap. But it works. And it makes code much, much more reusable.
RD: You talked about the birth of Zig from the digital audio workstation, and there's a lot of talk of the benefits of Zig on bare metal and making the standard library optional. Was there an intent in creating this and developing it to make it a basic bare metal language?
LC: Yeah, so the tagline they have for Zig—which I helped come up with—is “Zig is a general purpose programming language and tool chain for maintaining robust, optimal and reusable software.” We talked about reusability, right? That's one main point. If you want robustness and optimality, your language has to be low level because, well, optimality is kind of self evident, right?
One example of this is TigerBeetle, which is a distributed financial database, and they really care about robustness. For them, robustness is, of course, correctness, but also it's a database. It's really bad if it crashes, right? Even if it's out of memory. What they do is they basically allocate a bunch of memory up front at startup. Then they never allocate any more after that.
This is really nice, because your process is not going to be killed because it goes out of memory. That's a very nice property that gives extra robustness to your software.
There's another keyword that we use in the description that people don't really think much about, although it's really important. We define Zig as a general purpose programming language.The idea behind Zig is that it's not just for big computers, it's also for embedded devices, hardware, all kinds of things that have a microcontroller in it. For everything that fits that description, the idea is that you should be able to program it with Zig.
RD: That's what I thought when the standard library was optional. You want this programming language to be as small and as fast as possible. Do you have examples of Zig being used on devices?
LC: I can't point you to a startup, but I can point you to a project called MicroZig, which is a project run by members of this community who are basically writing a hardware abstraction layer. The idea is that you have a Raspberry Pi, for example, and you just specify in the build script what type of board you have, and then you automatically through comptime get type definitions that match your board—with the same number of pins, and all the pins map to the physical device, et cetera. That should make developing for metadevices much easier.
Another thing that we really care about is cross compilation, so if you are on Linux, you can build an executable for my class or for Windows and vice versa. It's nice, but it becomes critical when you're dealing with embedded devices, because with embedded devices, you're compiling on your computer and then uploading the binary blob to the device itself. So it's always cross compilation in a sense.
We already had two Zig conferences in person, and we ran a MicroZig workshop in both of them. What happened with these workshops was that people would show up with Windows laptops, Mac OS, Linux machines, and all these combinations like Arm, x86, etc. Every single time, people could just plug the device in and it would always work on the first try. Every time you compile something with Zig, you can depend on system dependencies, but Zig makes it very easy to avoid doing that so that you can make your software really portable.
RD: That’s very cool. I think it's interesting you say it's a language and a tool chain. When we first were emailing, you were only talking about the compiler, and I know the compiler is a big part of the language. Can you talk about why the compiler is so important?
Loris: There are two aspects to it. One, more general, is what I just described, cross compilation. But more specifically, we don't only support cross compilation of Zig code. We also support cross compilation of C and C++ code. So Zig is not only a Zig compiler, but it's also a C compiler. Not everything is made from scratch.
What we do basically is we bundle Clang [Ed. note: Check out our podcast with Chris Lattner, the original creator of Clang]. Zig depends on LLVM for optimizations, and since we already depend on LLVM, it's easy for us to also basically bundle Clang with Zig. When you run zig cc zig, the cc subcommand is a flag-compatible replacement for Clang. What happens, though, is that you don't get immediately redirected to Clang.
Zig does some pre-processing of the flags and adds some extra logic of its own. For example, if you do cross compilation, it automatically sets that up. Let's say that you're cross compiling from Windows to Linux. It automatically sets up the import path for the Linux libc, even though you’re on Windows. What compilers do, including Clang normally, is that they assume they just use the system one, which is not going to work for cross compilation.
It does caching. There's also a few other things that it does before you get to Clang. When it comes to C and C++, then it's not just a matter of the compiler itself and the libc dependency, there's also a few more tools they need to understand the target.
So, for example, the linker does target-specific linking for Windows, which is different from linking an executable for MacOS or Linux. There are a few other tools like ar and a few others that in practice, as a programmer, you don't really care much about most of the time, but they have to be there for cross completion to actually work.
The tool chain part is real. It's a 40 megabyte tarball when you download it, and it contains a bunch of versions of glibc. This is something that usually compilers don't do for you. Not only can you target glibc, but you can target a specific version of glibc.
Basically it's cross compilation, but not only for the language itself. For example, Rust can cross compile Rust, but can’t cross compile C. If you depend on a C library, then your experience when it comes to cross compilation is significantly different.
RD: It sounds like, by doing that, you have an automatic ecosystem to draw from, right? You get all the C libraries.
Another thing I wanted to ask. You’re VP of community and obviously Andrew was big on building community at the beginning. What's the Zig community look like today?
Loris: I think that the two most interesting things that I can say about the Zig community and the project is that first of all, the project is BDFL run. Compared to other languages, we have a BDFL—Andrew—that has a final say on all design decisions. He doesn't do everything. He doesn't make every decision completely on his own from the top of his high tower. Other core contributors and collaborators do have a voice in what we do.
But for example, people sometimes think that when there's a GitHub issue that has a language feature proposal, they think that the number of thumbs up influences the final outcome, but it does not at all. This is how the project is run at its core.
The communities around it are instead very liberal, and there is no official community and the community is decentralized, meaning that there is no official community place, aside from GitHub. There is, for example, a big Discord server, but it's not official. It's not run by Andrew or me. I'm a moderator there, but I'm not an owner, and the idea is that every community sets up their own code of conduct. They decide how they want to run their place.
This is, I think, very different from how other languages tend to do it, where they tend to have official places, but we don't.
RD: Especially ones with a benevolent dictator. They usually want to centralize the community.
LC: Yeah. In our case, we don't.
RD: A lot of languages have set up foundations to support them. Can you talk about how the Zig Foundation operates?
LC: Something interesting about the Zig Foundation is it’s not a 501(c)(6). A lot of other nonprofits are basically trade organizations, while we are a 501(c)(3), so we are fully tax-exempt and pay the developers.
All the money that we get, which is mostly from donations, but occasionally also something else like support contracts, 90-plus percent of what we get goes to developers with the rest being used for infrastructure, CI, and administrative costs.
We've had two in-person conferences, so we're still very small, but we had two conferences called Software You Can Love. They're not just about Zig, but they usually have two days dedicated to Zig: one workshop day and one talk day dedicated to Zig. Then there is one talk day dedicated to software in general. This is also another community building effort in the sense that it's not ZigConf. The idea is to put forward ideas that aren't specific to the language that we would like for every community member to always keep in mind.
RD: You want the community to be bigger than just the language. Because you're not just using the language all the time.
LC: Exactly. And also to be open to other communities. What's the point of making software? The point of making software is that all software in the end is for the utility of other humans. And that's what defines it in the end how good the software is. That's the ultimate goal, right?
Last thing, Zig Showtime was on hiatus for a couple of years. It started during the pandemic, then I got fatigued by online events terribly, like everybody, and that's when we shifted to in person events and meetups, etc.
And now that we're not fatigued anymore, I'm restarting Showtime again.
RD: I think we're all moving past the pandemic burnout stage.
LC: Yeah. It took a while and man, I was the host and I was getting tired of it. So I can't imagine how fatigued the viewers were.
RD: Always a good time to take a break.