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.
RD: There’s so many languages out there today, and so many mature ones. We always get a lot of Rust fans in thesurvey. Besides the metaprogramming, why do you think Zig came about?
LC: Why? Well, there’s an actual officially sanctioned story about the birth of Zig. Andrew wanted to create a digital audio workstation, a software tool to do real time manipulation of audio. That’s a very demanding domain because it needs to be real time. It needs to be fast. He tried a few different languages, tried Go, tried C, tried JavaScript. He always felt like they had shortcomings.
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?
You want to have precise control over the machine. Otherwise, you’re not going to do the optimal thing. But also robustness comes from that. For example, if you write something in JavaScript and you run out of memory, your program will crash. As the person who writes JavaScript, you don’t have an option to not crash because your language will have built-in features that expect memory allocation to succeed. If that fails, all they can do is crash at the engine level. But with Zig, that doesn’t happen. You can write programs that never crash because they run out of memory.
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 relies on LLVM for optimizations, and since it already depends on LLVM, it’s also basically easy to bundle Clang with Zig. zig cc When you run zig, the cc subcommand becomes a flag-compatible replacement for Clang. However, you will not be redirected to Clang immediately.
Zig preprocesses the flags and adds its own additional logic. For example, cross-compiling automatically sets it. Suppose you are cross-compiling from Windows to Linux. The Linux libc import path is automatically set even if you are using Windows. Compilers that include Clang typically assume that you are only using the system compiler and will not work with cross-compilation.
Do caching. There are a few other things that happen before we get to Clang. When it comes to C and C++, it’s not just about the compiler itself and libc dependencies; there are several more tools needed to understand the target.
So, for example, the linker performs target-specific links for Windows. This is different than linking an executable for MacOS or Linux. There are a few other tools like ar and others that I don’t really care about as a programmer most of the time, but they require cross-completion to actually work.
The tool chain part is authentic. The download is a 40 megabyte tarball that contains a large number of versions of glibc. This is something that compilers usually don’t do automatically. In addition to targeting glibc, you can also target specific versions of glibc.
For example, Uber uses Zig to cross-compile its Go programs. This is because the program depends on the libc system and some machines require a specific version of glibc.
It’s basically cross-compilation, but not just the language itself. For example, Rust can cross-compile Rust, but not C. The cross-compilation experience is very different if you rely on C libraries.
The same goes for Go. There’s a popular blog post that says cgo, the command you use to rely on C libraries, is not Go because it makes for a poor cross-compilation experience.
However, both Rust and Go can use Zig to provide cross-compilation of C and C++, so projects like Cargo Zig Build essentially do this job and provide cross-compilation of C dependencies. there is.
RD: That seems like an automatic ecosystem, right? You get all the C libraries.
There’s one more thing I wanted to ask you. You’re the vice president of community, and obviously he, Andrew, has been passionate about building community from the beginning. How does he feel about the Zig community now?
Loris: The two most interesting things to say about the Zig community and the project are, first of all, that the project is run by BDFL. Compared to other languages, we have BDFL (Andrew) who has the final say on all design decisions. He doesn’t do everything. He doesn’t make every decision entirely on his own from the top of a high tower. Other core contributors and collaborators also have a say in our work.
But, for example, if you have an issue with language feature suggestions on GitHub, one might think that the number of thumbs up will influence the final result, but that’s not the case at all. This is the core method of the project.
Instead, the community around it is very liberal, there is no formal community, and the community is decentralized. This means that there is no official community location other than GitHub. For example, we have a large Discord server, but it’s not official. It’s not run by Andrew or me. I’m a moderator there, but not the owner. The idea is that each community sets its own code of conduct. They decide how they want to run their place.
I think this is very different from how other languages do it. Other languages tend to have a formal place, but we don’t.
RD: Especially in countries with benevolent dictators. They usually want to centralize the community.
LC: Yeah. Not so in our case.
RD: Many languages have established infrastructure to support them. Can you talk about how the Zig Foundation operates?
LC: What’s interesting about the Zig Foundation is that it’s not a 501(c)(6). Many other nonprofits are essentially trade associations, but we’re a 501(c)(3), so we’re completely tax-exempt and we pay developers.
All the money we get comes mostly from donations, but sometimes from other money like support contracts. More than 90% of the money we make goes to developers, and the rest goes to infrastructure, CI, and management costs.
We’ve held two in-person conferences, so it’s still small, but we’ve held two conferences called Software You Can Love. We’re not just talking about Zig. There are usually two days of his work dedicated to Zig, one day of workshops and one day of talks dedicated to Zig. After that, he has one lecture day dedicated to software in general. This is another community-building effort in the sense that it’s not ZigConf. Its purpose is to suggest non-language-specific ideas that all community members want to keep in mind at all times.
RD: We want our community to be bigger than just a language. Because you don’t just use the language all the time.
LC: that’s right. And be open to other communities. What is the point of creating software? The important thing about creating software is that all software ultimately helps other humans. And that is what ultimately determines how good the software is. That’s the end goal, right?
Finally, Zig Showtime was on hiatus for several years. It started during the pandemic, and then, like many of you, I got really tired of online events, so I moved to in-person events, meetups, and things like that.
And now that I’m no longer tired, I restart Showtime again.
RD: I think we are all moving past the pandemic burnout stage.
LC: Yeah. It took quite a while, but I was getting bored because I was the host. So I can’t imagine how tired the viewers must have been.
RD: Any time is a good time to take a break.