Become a Creator today!Start creating today - Share your story with the world!
Start for free
00:00:00
00:00:01
What's Zig got that C, Rust and Go don't have? (with Loris Cro) image

What's Zig got that C, Rust and Go don't have? (with Loris Cro)

Developer Voices
Avatar
3.4k Plays1 year ago

Zig is a programming language that’s attempting to become “the new C” - the language of choice for low-level systems programming and embedded hardware. Going into that space not only puts it in competition with C and C++, but also other newcomers like Rust and Go. So what makes Zig special?

Joining us to discuss it is Loris Cro from the Zig Foundation. We talk through Zig’s reasons to exist, its language design features, which parts of the C ecosystem it's tackling, and how the Zig Foundation is set up for the long-term health of the language.

Loris’ website: https://kristoff.it/
Kris on Twitter: https://twitter.com/krisajenkins
Kris on LinkedIn: https://www.linkedin.com/in/krisjenkins/

Zig homepage: https://ziglang.org/
The “learn zig” guide: https://ziglearn.org/
Learn Zig with Ziglings: https://ziglings.org/
Find the Zig community: https://github.com/ziglang/zig/wiki/Community
Rust’s cargo-zigbuild: https://github.com/rust-cross/cargo-zigbuild
Using zig as a better linker: https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html
"The Economics of Programming Languages" by Evan Czaplicki (Strange Loop 2023) - https://youtu.be/XZ3w_jec1v8

#programming #programminglanguages #software #zig #llvm #rust #go

Recommended
Transcript

The Challenge of Replacing C

00:00:00
Speaker
One trend we've seen a lot in programming in recent years is the attempt to replace C. And I think that's both wise and terrifying. It's wise because C is about 50 years old. And being old doesn't make it bad, but it has given us five decades to think about what works and what doesn't work in programming language design. We've got 50 years worth of techniques we really ought to be putting into practice.
00:00:27
Speaker
And putting them into practice is the terrifying part because C is everywhere. You may not write C, but I guarantee you're writing something that runs on something that runs C and was written in C. It's in the compilation stack for everything we install.

Zig's Ambitions Beyond C

00:00:44
Speaker
So if languages like Go and Rust want to become the new C, they've really got their work cut out for them.
00:00:51
Speaker
All of which makes this week's topic kind of breathtaking. We're looking at Zig. It's a language that's not only trying to take on C and C++ and Rust and Go for that systems programming crown, it's also trying to replace the infrastructure that C itself gets built on, things like LLVM. So it can hopefully become the best way to build systems level software across all different architectures.
00:01:19
Speaker
Zigg ends up being a project with a huge scope and if you're a fan of programming languages, there is a lot to chew on this week. We cover cross platform compilation to memory management techniques to new thoughts in compile time metaprogramming. As well as when you've got these huge long term ambitions, how do you structure an open source project for long term funding?
00:01:43
Speaker
There is a lot of ground to cover, so this is a bit of a longer episode than usual, and we'd best get started. I'm your host, Chris Jenkins. This is Developer Voices, and today's voice is Loris Crow. I'm joined today by Loris Crow. How are you doing out there, Loris?

Initial Interest in Zig

00:02:11
Speaker
Hello. Hi, Chris. Pretty good. Thank you. Good, good. It's good to have you here. I always love it when we do a language deep dive, because I'm a particular fan of the world's programming languages. And you're going to tell us all about Zig, which is a language I don't think I've heard of until we had, uh, Yoren Grief on the show from Tiger Beetle, who said they've written a new database in Zig. And I thought, well, we have to do something about Zig. I have to learn about that.
00:02:38
Speaker
So let's start here. I always think new programming languages come into being as a reaction to what's missing in the marketplace, if you like. There's a burning reason why Zig needed to exist. Do you think that's true? What's Zig's raison d'être? Right. So...
00:03:02
Speaker
I guess a way of answering this question factually is maybe to look at how it was created originally. The original creator, Andrew Kelly, wanted to make a digital audio workstation software. For making electronic music and that kind of thing. Exactly.
00:03:25
Speaker
And he tried a bunch of different languages and he was unhappy with all the solutions, with all the trade-offs that each offered. So I think he started with higher level languages and then quickly found out that to do real-time audio processing, you can't use a language with automated memory management and languages that don't give you precise control over the hardware.
00:03:53
Speaker
Yeah, because audio is one of those places where we're talking hard real time. Exactly. You have to be there on time.
00:04:02
Speaker
Yeah.

Limitations in C/C++ and Zig's Advantages

00:04:03
Speaker
But on the other end of the spectrum, at the time, the main languages that did give you full control over the machine were C and C++. And each had its own, if you will, baggage of issues, which some of it is also up to personal taste.
00:04:24
Speaker
But for example, C is very low level, but it doesn't have good metaprogramming facilities. C macros are very well known for being not particularly good. Yeah. Yeah. They're not much better than string managing, right? Yeah, exactly. You mess around with strings and you have a lot of unwanted side effects.
00:04:48
Speaker
often times. So it's a food gun. That's how we usually think of it. Yeah. On the other hand, you have C++, which I don't know if he actually did attempt to use, but in general, C++ exists in a space
00:05:04
Speaker
where the language is very powerful, it's very complex, and it's a type of language where you are heavy with abstractions oftentimes, and that kind of detracts from what you're trying to accomplish, or rather, some people can definitely make it work for them, and that is their preferred way of programming, so that's good. But for some other people,
00:05:31
Speaker
C++ doesn't really, you know, it doesn't feel good in your hand as a tool for some people. Yeah. I can see how people, we're not going to start a language war, but you can certainly see how people would feel that way about C++. Absolutely.
00:05:50
Speaker
And to me, this is not really a thing of language war at all. I can fully appreciate how somebody who likes that way of doing things can make it work for them. But on the other hand, for me personally, that way of doing things doesn't really click. So ultimately, I can totally see how somebody would be productive with C++, and I wouldn't. So I need a different tool.
00:06:17
Speaker
And I think that Andrew also shares, generally speaking, this perspective. So he wanted to make a language that was low level, so they gave you full control over the machine that would be suitable for an audio workstation. And that, on the other hand, it wouldn't be overly complicated.
00:06:40
Speaker
And there's like a sentence that you can you can find in like zigs on the website where we say it's one of the first things that you can see on the front page. It says focus on debugging your application rather than debugging your programming language knowledge. Right. Yeah. Yeah. OK. So that's kind of
00:07:04
Speaker
I know people, anytime you write something that's sort of competing with C in the low-level world, someone says, well, why not go and why not rust? But you begin to demarcate those as... I'll let you answer it. Why is it not go or rust?
00:07:23
Speaker
The reason why it's not Rust, I would say the answer is very, in a very general way, it's kind of the same answer as why not C++. I think that Rust is another language that likes its own complexity and it gives a ton of power from that for sure.
00:07:40
Speaker
But the complexity is there. And also, when it comes to giving you full control over the machine, Rust, it's not entirely of that opinion. For safety reasons, Rust wants to
00:08:02
Speaker
relegate certain things inside unsafe Rust, which is a part of Rust that you are not supposed to use lightly. So that means that you will find out their libraries that when choosing between maximum performance
00:08:19
Speaker
In safety, they will choose safety, probably overperformance oftentimes, because you do get audited if you have unsafe or not. So in general, Rust is going for something slightly different than what Zig is going for. So both in terms of trade-offs between performance and safety, but also in terms of
00:08:41
Speaker
And I would argue also readability in terms of the complexity, because writing abstracted code makes it harder to understand and to read for a consumer. When it comes to Go, I think that Go and Z both share
00:08:59
Speaker
an appreciation for simplicity, although Go is not just simple, it's also very minimalistic. So I would say that there are some parallels between Zig and Go, but we don't have the exact same take on everything. And I can get more into detail if you want later.
00:09:19
Speaker
But ultimately, Go is not as low-level as Rust and ZigR. I am not sure if Go would be the best choice for an audio workstation, for example, or for an operative system, because Go has a runtime, has a garbage collector. Also, interoperability with C is a bit complicated in Go.
00:09:43
Speaker
Well, first of all, any language that has a runtime, that makes interoperability with C a little bit more complicated because you need to give information to the runtime of your language to the garbage collector about what's going on with memory. And so that sometimes makes things a little bit awkward.
00:10:03
Speaker
But with Go specifically, I do think that for the Go team, interoperability with C was never a priority or something that they really liked. So, Go can call C functions, for example.
00:10:19
Speaker
But you cannot do the inverse easily. So you cannot make a Go function that can be easily called from C. And I think basically this is like a philosophy of the Go team. They basically said, no, we want to do something different. We don't want to do something... We don't want people to rely too much on... We want to be able to consume C libraries, but we don't want to do the inverse. If you're in Go land, you use Go. I think that's kind of their philosophy there.
00:10:46
Speaker
Yeah, it's like we want to be able to reuse existing C, but we're not intending to live in the same ecosystem quite. Yeah, exactly. I would say that. And you can see that also in a bunch of choices that they made also with how compilation works in Go, like in terms of the compiler. And I think it's a reasonable choice. It's a choice. It makes sense. Very different from what Zig is going for.
00:11:11
Speaker
Yeah, I don't think we need language wars because there's a huge design space to be explored and there's plenty of land for everyone. Okay, so that demarks what you want to be. What's Zig's answer to this set of design constraints?
00:11:34
Speaker
I think the most interesting part about the answer to, let's say, systems programming, like lower-level programming in general, is to rebuild it from scratch.

Cross-Compilation and Innovations with Zig

00:11:45
Speaker
All these other languages that I... Well, not all these other languages, but it is common to consider, kind of like, see the bottom layer of abstraction of what you're building. So, for example, there are programming languages that compile to C code. I think Nim is an example of this.
00:12:04
Speaker
And Rust itself, Rust doesn't compile to C. But for example, Rust depends on the C standard library of the platform that you're targeting. So if you're writing a Linux program, like a Rust program that you want to deploy on Linux, Rust will use the libc of your Linux distribution.
00:12:28
Speaker
With Zig, the idea instead is to really, really build everything from the bottom up. And this is a big scope. This is not like for the faint of heart. It's a lot of work. But it does yield some very good results, like some very good things that you can do once you are willing to do that work.
00:12:54
Speaker
I would say that the most important interesting thing about zig is that it really is a language that allows you to build for every target from any target, meaning that if you want to target like not just normal computers, but also very tiny embedded devices, you can do so easily.
00:13:14
Speaker
And that's also cross-completion because you're compiling on a Linux machine probably, which is going to be maybe x86-64, and you're targeting a very tiny ARM V8-embedded device. So you're compiling for different architecture there. But this is also true from computer to computer. So with Zig, it's considered fundamental, the ability to build your program for
00:13:39
Speaker
Mac OS, Windows, Linux, from any of those other OSes. So from Linux to Windows, from Windows to Mac, etc. That's surprisingly rare. Yeah. But a very nice feature.
00:13:50
Speaker
And it doesn't end here because we can do these for Zig applications. And to be fair, I think the Go can do it for Go, Rust can do it for Rust, but they cannot do it for C. Well, we can do it also for C and C++. So the idea is that if you have a project that has Zig code in it and also a C dependency, not only you can first compile the Zig part, but you can also cross-compile the C part
00:14:17
Speaker
Really? Yes. And that is, I think, the huge thing. And it's so big that actually you can use Zig as your C C++ compiler
00:14:29
Speaker
when you are trying to cross-compile a mixed project between Rust and C or a Go and C1. So for example, Go people have been using the Zig Compiler to close the circle, to enable complete cross-compilation of
00:14:47
Speaker
Seagull programs. Seagull is basically what you call a project that has both Go and C in it. Seagull is like a component of the Go compiler. That's how they compile in a link to Seagull. So people using Go projects, they are using Zig to cross-compile. And same with Rust. Even AWS is using Zig to cross-compile
00:15:15
Speaker
Rust lambdas for the lambda engines because rust depends on the libc of the target and their machines running lambda functions are running a specific version of Linux with an older libc.
00:15:32
Speaker
And you need to be able to target the correct version of the libc to make sure that everything runs smoothly. And that's not something that normally compilers can do. And Rust itself, which doesn't concern itself with C compilation at all, certainly cannot do. So there's a package called Cargo Zig Build that allows you to use Zig to basically link against the correct libc version that works on Lambda.
00:15:59
Speaker
How on earth is that working? Are you telling me that Zig also has a C compiler built it and all? Yeah, he does.
00:16:07
Speaker
It straight up does. Okay. Andrew started out trying to build an audio workstation and ended up building a language that also includes a C compiler. Yeah, pretty much. That's legendary. Yeah. And this is like, I would say we're like halfway through the journey because we want to get even more hardcore than this. So, I mean, if you want, we can change subject. Otherwise I can keep doing it. No, I'm fascinated. Keep going. Yeah. Okay.
00:16:36
Speaker
So, do you remember when Apple released the M1 architecture, right? Yeah. They went from Intel to ARM. And that was big news because, well, it turned out it's also a pretty good CPU, like a pretty good architecture. Numex, I would say, are pretty nice. They're powerful, they overheat less. They're nice.
00:17:02
Speaker
When Apple released the M1, Zig was the first compiler
00:17:08
Speaker
it was able to cross-compile 4M1 from another target, from another machine. So, Apple obviously, when they released, not only when they released, but also while they were developing the M1, obviously they had a tooling to compile for the M1. But they never released, or rather, when everything came out, they had not released any tooling for compiling 4M1 from another machine.
00:17:37
Speaker
Oh, so you had to buy the new Mac in order to build for the new Mac. Exactly. Because what you would get was when you have macOS, you get Clang. You get a fork of LLVM. I would say it's kind of pretty much LLVM, except with private patches that Apple makes specific to their system.
00:18:00
Speaker
And when the M1 came out, they had patches specific to the new architecture. So you could compile obviously from M1 to M1. But LLVM itself, the open source project, did not support M1 yet.
00:18:16
Speaker
fully. And so you could not get LLVM on Windows or Linux and then use that to compile for macOS. We were the first ones. And that was because not only Zig is a C compiler, and to be fair, the C compiler stuff right now, I would say at its core, it's not super impressive. The idea is that Zig uses LLVM. And LLVM is like this library that allows you to
00:18:39
Speaker
It's like a unified framework for generating optimized machine code. So the idea is that your compiler reads the program that it's trying to compile, builds a data structure in memory, does semantic analysis, all the user stuff that a language has to do, but then the final step
00:19:00
Speaker
is to give some of that information to our OPM, which will then take care of selecting which exact instructions to use for the for the CPU that you're targeting. Right. So it's I suppose I want to say it's almost a little bit like WebAssembly. It's like a very low level language that's actually going to generate the final machine code.
00:19:26
Speaker
Yeah, a bit of a stretch, but I think that's fair. That's what that's the that's called the LLVM IR intermediate representation. Yeah, that's what you create, which is a bit code of some kind and byte code, sorry, of some kind, kind of like a WebAssembly. I think that's a fair parallel. Yeah. OK.
00:19:49
Speaker
Yeah, so we give that to LLVM. And since we're already bundling all of LLVM, it doesn't take much to also add Clang, which is the C compiler that runs on LLVM. So that's what allows us to build C. There's more than Zig does, but at its core, it's not super complicated.
00:20:07
Speaker
But a compiler is just one step necessary to create a final executable. There's also a linking phase at the end. So the main problem with the new M1 max was that linking needed to be different than it was in the past. And the reason why we were the first ones to be able to cross-compile for M1
00:20:35
Speaker
was because we had our own in-house linker. There's a core team member in the ZIG project. His name is Jacob Konka and he used to work at Microsoft and we kind of approached him to work. Well, I guess he approached himself. He wanted to work on linkers. I think at Microsoft he was not working on anything even remotely as exciting.
00:21:00
Speaker
And so he decided to jump ship and join the project full time. So we have our own link here, and most of the work is done by him. And so my point here is that by having our own link here, we were able to reach to have a feature even faster than LLVM could.
00:21:21
Speaker
And LLVM is considered, in general, a very good project. And it is. And it is. Yeah. But the point is that we did not consider LLVM the baseline. We were willing to get past LLVM and do some of that work ourselves. And now, going forward, and this ties back to my point that we are only halfway through our journey. Now, going forward, we plan to make LLVM a completely optional component. So that means
00:21:49
Speaker
that we have our own implementation of some of what LLVM does. So we have what we call them backends. So we have our own implementation of what reads the internal representation of the compiler, the internal data structures, and decides which instructions to output.
00:22:10
Speaker
That's a lot of work because you have to build one of those things for each Architecture they want to support so you want to support x86 64. That's one implementation arm 32-bit another arm 64-bit x86 like 32-bit x86. That's another one There's more architectures out there. So for each one you have to write a specific one and then you have to write a
00:22:35
Speaker
Another bit based on the OS that you're targeting. So like x86-64 Windows is a little bit different than x86-64 Mac. Not in terms of like the instructions of the program, but like the packaging. Like how an executable is structured, all the like surrounding metadata, the frame in a sense. Right, yeah.
00:22:57
Speaker
And we are doing it now. The work that we're doing in that regard right now is not to replace LLVM in terms of optimizations. So the bulk of what LLVM does and what it's considered state of the art for is optimizations. We are not doing that yet. What we're doing right now is basically do the work so that we can have debug builds, which are not optimized, happen without needing LLVM at all.
00:23:28
Speaker
That's our starting point. But the plan is going forward to basically have a competing optimizing backend. So you will still be able to use LLVM if you want. How it's going to happen in practice, it doesn't matter much. I think it's going to happen that you basically will need to get LLVM through the package manager.

Zig's Future Developments and Independence

00:23:48
Speaker
So you will use the Zig package manager to get LLVM instead of
00:23:52
Speaker
getting it bundled in the compiler itself, but then you will be able to get an LLVM optimized final executable regardless. But we're going to work on our competing version and you will decide which one you like more. And over time, if we do a good job, it might even be that our competing backend becomes compelling enough that people will use that one over LLVM.
00:24:16
Speaker
Crikey, you're not kidding about going all the way down to the lowest level, right? Yeah, geez. Yeah. Okay. That's, what's your timeline for that?
00:24:28
Speaker
That's got to be a multi-year project, right? 100%. Yeah, for sure. Honestly, I don't know what the timeline is going to be. The reality is that the timeline of these things can vary dramatically depending on the amount of talent that you attract. One thing that people usually
00:24:49
Speaker
say when we first tell them, yeah, we want to get rid of LLVM. They start by saying, oh, you're insane. You're never going to be able to do it. There's a bunch of geniuses that work on LLVM. Fair. Fine. Let's assume that that's right. I mean, I'm sure that the people working on LLVM are smart. But it's not like they are bound by a blood contract to work on LLVM.
00:25:15
Speaker
And working on LVM, it's a humongous C++ project that takes forever to compile. And it's, in some ways, it's messy. What if we were to be able to present to people working in that field another ecosystem where they can research the same exact kind of optimizations that they are researching and implementing on LVM,
00:25:43
Speaker
But the compiler, instead of taking four hours to build, it takes 20 seconds. I imagine that would be very seductive. And I think you're deliberately trying to seduce people over to the zig side, which is fair enough.
00:26:00
Speaker
And I mean, we already have people in the core team who have pushed access to LVM. So it's not like we are like... Well, I don't know anybody who is part of the leadership of LVM, so I wouldn't say we are like insiders. But we already know people who do this. So...
00:26:23
Speaker
Yeah. Sounds like there's potential for both knowledge sharing and maybe some more kinds of sharing out there. Absolutely. And if our VM also ends up benefiting from this, it's great for everybody. Sounds like one of those whoever wins, we all win situations. Absolutely. Okay. This is getting very low level. Maybe we should try and pull it back into user space.
00:26:47
Speaker
I love the ambition though, absolutely. But I do want to get a sense of what it's like to write Zig. What am I going to find as a programmer? What am I going to like? What am I going to need to learn? The hardest part about Zig
00:27:06
Speaker
is not Zig at all. Zig as a language is very, very simple. The most complicated part of Zig right now is comp time, which is the ability to run code at compile time instead of runtime. And if you're not used to thinking about the two different
00:27:27
Speaker
lifetimes of your program, the two different phases of its life, then you might get a little bit confused about what it is that you can do at comp time or what it is that you cannot do at comp time. But overall, the core principle is, in my opinion, kind of straightforward. Where things get complicated is once you get into systems programming more in general. So if you are like a JavaScript or a Python developer,
00:27:54
Speaker
And you never had in your life to think about stack versus heap. Or maybe people told you, but like if you're a Python programmer, this is something that also happened to me like in university. If you do Python and people tell you about stack versus heap, that's like philosophy to you because that's right. You don't have control. Fascinating, but you'll never use this knowledge. Exactly. Like you don't have control over it. And yeah.
00:28:19
Speaker
But when you're getting to low-level systems programs, suddenly this becomes a real concern, right? Exactly. And so the hardest part is, for example, understanding the difference between an array of whose length you know statically. This is going to be a six-element array, and it's always going to be six. Or maybe you need up to six slots. Maybe at some point in time you use fewer than those, so you have a counter that tells you how many
00:28:47
Speaker
slots you're using, but six is the limit. So, and if you know this statically at compile time, then this can be put on the stack. And there's some things that you can do with this memory, thanks to the knowledge of the fact that it's bounded to six elements. And you know exactly how much memory is going to need for the whole lifetime of the program.
00:29:08
Speaker
Exactly, and that is critical information for the compiler itself. The lower-level languages are designed around these very critical concepts of what you know statically and what you do not know statically. For example, instead, you have a program where you ask the user to tell you how many items they want to enter, and they are allowed to enter 10,000 if they want.
00:29:32
Speaker
Or more realistically, imagine parsing a JSON file. Like a JSON file can be arbitrarily deeply nested or big in general. So at that point, you need to concern yourself with heap allocation, which again, is something that in Python and JavaScript, you don't do directly because the runtime manages that for you.
00:29:57
Speaker
So that's one example. Another example is things that your platform, like APIs that your OS, operative system gives to you, which people sometimes are used to think about as in terms of capabilities that the language gives to them, even though the language can only act as an intermediary. So for example, sometimes people ask, how do I get the size of the terminal window in Zig?
00:30:26
Speaker
And the answer is, well, the real question is, how does your OS allow you to get that information?
00:30:36
Speaker
And then, and that's going to happen through a syscall of some kind, and then, I guess the secondary question is, well, has somebody written the boilerplate to access that syscall, and where is it in the Ziggs standard library? So the question of how you do this kind of stuff in ZIGOR in each specific language, it's not completely wrong. It does make sense.
00:30:59
Speaker
But understanding what is the actual API below you can be a little bit annoying, especially when the language wants to show you precisely what that is and it's not trying to give you a sugared interface that is overly simplified.
00:31:19
Speaker
because sometimes you do also get that in other languages, which might make sense, like a higher level programming language, it makes sense that it doesn't give you necessarily low level access to everything.
00:31:30
Speaker
So I would say these are the biggest challenges. People need to learn systems programming. They need to have this mindset where they have to think, okay, for another example, people sometimes ask, how do I print colored text in the terminal? How do you do that in Zig? And the answer is Zig doesn't concern itself with this. These are escape codes. It depends on which terminal military you're using and a bunch of other related concerns that really are pretty much transparent to Zig.
00:31:58
Speaker
uh but people don't have this mindset so i would say that is the hardest part about learning z and connected to this there aren't a lot of good learning materials in my opinion. So this sounds like the usual kind of youngish language problem where maybe there isn't a library for everything yes and there aren't there isn't documentation for everything yet.
00:32:23
Speaker
Yeah, for sure. But also, I mean, it's not like Zig has invented systems programming. So it would be nice, right, if there was some good piece of like a good book that taught you the core principles without too much fuss. And in fact, there are plenty of books that try to teach you these things. It's just that in my experience,
00:32:47
Speaker
Most of those that I've seen, they tend to conflate C-specific stuff with the OS. So for example, you have this book that it's trying to teach you systems programming, and it starts by telling you about how the C completion model works.
00:33:05
Speaker
and how that intertwines with how libraries are, certain files are laid out in your system. And this is all real and concrete, and it was especially real and concrete like 40 years ago. But those concepts and other things like macros and where things are usually in the system library, but those are things that are
00:33:30
Speaker
specific to C. So if you're not doing C, a lot of these things are not as timeless as the book thinks they are. While instead, stuck versus heap, that one is much more timeless. So personally, I think that we're missing learning materials that can discern between really timeless systems programming concepts, like stuck versus heap, versus C-isms that are not relevant anymore.
00:33:58
Speaker
Yeah, yeah, that's a sort of long life cycle, but not mathematically pure, you can almost say. Yeah, yeah. Okay, so I would like to talk about how the C interrupt works, and maybe this is the way to do it. So if I'm actually looking to get the size of a terminal window,
00:34:21
Speaker
Am I going to go looking for a sys op call and find I actually have to do it through an OSC library? And how's that going to play out when I actually start coding? Well, I guess it depends on the OS. Let's assume that the OS is Linux, OK? For simplicity. So if the OS is Linux, you're in luck. Because in Linux, the sys calls are considered a public API of the OS.
00:34:48
Speaker
So you are not forced to use the C library of your OS. You can invoke the syscalls directly. And in the case of Zig, since we like doing things from scratch, you will find in the Zig standard library that we do implement the syscall, which I think it's IOCTL, the syscall that you can use to get that information.
00:35:11
Speaker
from the OS. So in the case of Zig, in the case of Linux, that's how you find that out. But in other platforms, yes, you would have to use a C-lib, although we do have also bindings to the C-lib. So in practice, you wouldn't have to do everything yourself from scratch.
00:35:36
Speaker
when it comes to like these very common things, but let's imagine that instead you want to use like a C library.
00:35:42
Speaker
Let's imagine that you want to use, I don't know, SQLite. By the way, SQLite is a perfect example of a very popular library used, for example, by Go. There's a lot of Go projects that bundle SQLite, but SQLite is a C project, so that's one major use case of people using Zig to do cross-completion when they also want to bundle SQLite. Anyway, you want to use SQLite.
00:36:08
Speaker
At its baseline, here's what you want to do. The way this stuff works in C is that you have C files that contain implementations of things and have header files, which are files with a .h extension. And those files contain definitions.

Compatibility with C and Memory Management

00:36:25
Speaker
So they do not contain the full implementation. They only contain the signature of a function, for example. Yeah, the original API docs, right? Exactly. The original API docs.
00:36:36
Speaker
What's it called? Is it called OpenAPI, I think? The thing that used to be called Swagger, it's a system to document RESTful APIs, right? That's kind of the idea, except systems programming. The way this works is that then SQLite comes with a bunch of C files and one header file that you are supposed to include in your project to get access to the public API.
00:37:04
Speaker
With Zig you can do that directly. So in Zig you can import a C header file and it will work right away. Like you import that and you immediately get access to all the definitions in there. Oh, interesting. Okay, so there's no kind of bridging file that you have to write.
00:37:22
Speaker
Well, the bridging file, in a sense, gets auto-generated. That's the idea. Right. OK. So you don't see this. And actually, if you do want, you can do that manually. You can take the header file, translate it to C definitions. And in case there's the need to tweak something manually, you can do that if you want. But the happy path, the most common way you will want to do this, is just straight up import the header file and have Zig do that bridging internally. OK.
00:37:53
Speaker
Then at that point, you can just straight up call all the SQLite functions they are defining there. You can just go read the SQLite documentation and they will tell you call, I'm making this up, I don't remember how to use SQLite. There's going to be maybe SQLite. This is a test of the SQLite header API syntax, don't worry. There's going to be maybe some SQLite init function. You just call it and it works.
00:38:23
Speaker
There's also a couple other things that Zig does that help you with the interoperability with C. For example, C uses null terminated strings a lot. When you want to give to a function a string, you give it a pointer to the beginning of the string, and the pointer doesn't carry information about the length. The length will be discovered
00:38:46
Speaker
by the function that you're calling, by iterating through the string until it encounters a zero character, like a zero byte. Once it finds a zero byte, it knows that the string is over. Modern languages don't like to do that anymore. Modern languages very much prefer something else. I'll tell you my age. I can remember when we didn't like to do it at the time.
00:39:11
Speaker
So in Zig, for example, normally a string, it's not just a pointer to the beginning of some data without null in the end. But in Zig, we use slices, which other languages sometimes call five pointers. So the tiny, what you call the pointer is a pointer, but also a length.
00:39:32
Speaker
So yeah, you have both informations. And to be fair, sometimes in C you also have APIs that want a length. They don't want to discover a null byte at some point, but they want you to pass in a length. But those have always to be two separate arguments, two separate values that you need to move around in parallel. Anyway, so how does Zig help with C interoperability? Well, string literals in Zig
00:40:02
Speaker
are null terminated. So basically, when you write, I don't know, Hello World, and you want to use that string literal in Zig, that's going to be a pointer plus a length. I don't know how long Hello World is. 10 characters, 9 characters, whatever. It depends whether you include the traditional exclamation mark at the end. OK. So you do have this information. But there's also going to be a null byte past the end of the string.
00:40:29
Speaker
So you can take a ZIG string literal and pass it to C transparently. No need to do anything else. And it's always going to work. And more in general, ZIG does have a bunch of functions in the standard library that allow you to deal with null terminated strings, which are not the preferred type of string in ZIG. You don't treat strings as null terminated normally.
00:40:55
Speaker
ultimately, strings are a reality because not only because of C interoperability, like in terms of SQLite, but also because of C interoperability with the OS, like OS APIs, the libc, that's C, but also the syscalls oftentimes inherit some CS and some like some ways of communicating data that are like mirroring what C does.
00:41:17
Speaker
Yeah, unsurprisingly. Often the OS is written in C. Exactly, because the OS is written in C, because that's maybe how people used to do things at the time. And so these things are still there. Yeah.
00:41:29
Speaker
Yeah. Okay, so to conclude, you have string literals. You have a lot of other operators in Z that you can also use with Z functions very easily, kind of transparently. But just to name one that I think is really cool, you can use the fer. So the fer is
00:41:51
Speaker
Almost the same concept as goes defer. There's like some minor differences but the idea is that basically if you want to
00:42:02
Speaker
free a resource while when exiting the function, instead of making sure that you call free or like file close, for example, like whatever results release function you need to call, instead of making sure that you copy paste that call at every exit point of your function, what you can do is on one line, you open a file and on the line below, you defer close it.
00:42:27
Speaker
Oh, okay. Yeah. So you have basically cleanup that you can put immediately after the creation of the resource. And whenever you leave that scope, no matter how you leave it, whenever you leave that scope, that function will be called.
00:42:45
Speaker
Yeah, because it's always deeply dissatisfying that you have to remember to stick the close call or the free up call at the end. It just screams this is going to get forgotten one day. Yeah, absolutely. So the fair saves you from having to be too careful about branching paths in your function.
00:43:07
Speaker
And if you look at it from a... Maybe it's not as handy as what C++ can do with React with destructors. They run automatically. You don't even have to write the fur. But C++ destructors only work with C++.
00:43:23
Speaker
The fur in Zig also can be called on C functions. It's completely transparent. So there's this funny end result where basically Zig, in a sense, is better at using C libraries than C.
00:43:40
Speaker
because the same cleanup routine in C would require you maybe to even use GoTo. It's not uncommon for people to use GoTo and have a label, like a section of the function with all the cleanup functions, but it gets really messy. I don't think I am able to fully convey how messy cleanup can get in C because it doesn't have the fur. I can believe. Yeah, absolutely. That's interesting. That's interesting still being in C but building on it with new syntax.
00:44:10
Speaker
I have to ask, before we leave this particular thread, what about pointers? Does pointer arithmetic come into ZIG?
00:44:20
Speaker
Pointer arithmetic can come into Zig. By the way, that's a great point. I was forgetting. That's another great improvement overseas that also helps beautifully with interoperability. So you can do pointer arithmetic in Zig if you want to, because that's what the machine allows you to do. And maybe occasionally some OS API will require you to do so. But in general, you do not do pointer arithmetic in Zig.
00:44:48
Speaker
And specifically in Zig, you cannot do so in the type system, you are not allowed to do arithmetic on pointers. What you have to do is take your pointer, convert it to an integer, which is not like an operation that does anything at runtime. It's just like
00:45:06
Speaker
a type system thing. You have to be explicit about taking a pointer, interpreting it as a number, apply the math to the number, and then convert it back to a pointer. So you can do it if you want.
00:45:21
Speaker
Or if you need, probably if you need, you shouldn't want, but the language is not going to make it easy or like very comfortable to you. There's a little bit of friction introduced there. And on the flip side, it helps identify very quickly where these kinds of shenanigans are happening. Right. So it's mainly there for the sake of C interop rather than
00:45:46
Speaker
writing Zig day-to-day. Exactly. And I mean, we say C interrupt, but I don't know. There might be other things out there, like I'm thinking of firmwares, like you're programming a tiny embedded device and you need something like this because of the very low-level stuff that you're doing, which is not really necessarily specific to C anymore, but it's like super low-level bitfiddling. Maybe at that point you need something like this.
00:46:11
Speaker
Otherwise, you normally don't. And still related to pointers, there's another crucial thing. Pointers in C are very underspecified in the sense that you see a char star, so you know it's a pointer, and when you dereference it, you get a character. But then the question is, can that pointer be null or not? You don't know. Maybe documentation tells you, but you're not sure normally.
00:46:38
Speaker
The second question is, okay, I'm getting a character at the end of this pointer, assuming it's not null. Now, is there going to be just one character on the other side or is this like a string? Is this expected to have another character afterwards and another one afterwards until I encounter a null? Is there going to be a null or am I supposed to know how many items to get because of another variable? This is not encoded in a type system at all. In Zig,
00:47:02
Speaker
All of these are different type of pointers. So if a pointer can be null, it's an optional pointer. So we do the thing that all modern languages are doing, where you have the concept of optional, and then you need to unwrap the optional. And we use that to represent null pointers. But then we have types for... So you have normal zig slices, which are a pointer and in length.
00:47:24
Speaker
But then you have a C-style pointer that's going to be a pointer either to one item, one specific item, so you're explicitly saying there's going to be one character, one char at the end, not many. Or there's syntax for saying, no, this is like a pointer to a unknown number of characters. So there's specific syntax that is going to tell you, yes, this is a pointer to many items, but the pointer itself doesn't tell you how many.
00:47:52
Speaker
And then there's a pointer to an unknown number of characters with a null terminator at the end. And this is in the type system. So for example, if you, by mistake, think that you're trying to create a string off of another string, and so you maybe take a tiny slice from the middle of the string, and you try to pass it to another application,
00:48:15
Speaker
And you forget that that API is expecting an alternative at the end, which is not going to be there because you just split off like a tiny, like two characters from the middle of a string, right? So there's not going to be an alternative on the other side. The ZigType system will tell you, it will give you a compile error because it will tell you, I'm expecting an alternative string, but the...
00:48:37
Speaker
The slicing operation that you did on the other string does not yield an r-terminated string. So you will get a compile error right away instead of having your program read random garbage and maybe sometimes crash. Yeah, yeah. That's one other question I have to ask you then, because I can see right now this appealing to people that need to use C, don't want to use C, got into Rust, didn't make friends with the borrow checker.
00:49:07
Speaker
And now I could find Zig being the ideal place if I want more type safety around C, particularly around strings. What about memory management? Because that's the other big sticking point. Right. Yeah, agreed. So in general, if we want to talk about
00:49:30
Speaker
If you want to talk about ergonomics, what I described earlier, the first statement, that really helps a lot with memory management. Because you allocate a resource, defer, free it, and you're good to go. You need to remember to free it. There is an explicit malloc-free call in Zigland.
00:49:49
Speaker
Exactly. And to be even more concrete about this, Zig does not have a global allocator. So in C, you have malloc. And malloc is like the allocator. And maybe different projects use a different implementation of malloc. There's like a few competing implementations. But in Zig libraries, there's this idea that in C libraries, there's this idea that you have
00:50:17
Speaker
malloc coming from the ecosystem that allows you to allocate memory. In Zig, allocators are always passed around explicitly. So if a function wants to allocate, it needs to accept an allocator as input. Interesting.
00:50:34
Speaker
Yeah, so this makes it more easy, dramatically more easy to audit what it is that's allocated memory or not. If a function doesn't accept an allocator or a data structure that bundles the allocator in it, like it's also like, for example, we have ArrayList, which would be like the equivalent of a C++ vector.
00:50:53
Speaker
So it's a growable array. When you make an ArrayList, you give to it an allocator, and then when you pass around the ArrayList, the ArrayList will be able to allocate because it bundles a reference to the allocator inside of it. That's for convenience. But in general, you can very quickly audit if a function can allocate or not. Does that help you audit if a function is forgetting to deallocate?
00:51:24
Speaker
That by itself, no. What it helps is that the doing that is that the what we call the general purpose allocator, the main allocator implementation that you find inside of Zig in the standard library. That allocator in debug mode has leak detection.
00:51:43
Speaker
So you cannot check statically if all allocations are freed or rather you can't unless you're willing to become rust. Rust can. With all the limits, they also have limits on the type of memory management strategies that the border checker can understand. But they can, we can't. But we can instrument the default allocator with checks for leaks in the bug builds.
00:52:13
Speaker
So when you run your tests, basically the allocator will fail the test if at the end of it, you have like still memory allocated. Okay. And that's default built in part of the test suite. You don't have to specifically instrument. Exactly. You don't have to do anything.
00:52:30
Speaker
Oh, that's nice. Yeah. There's another angle to this also, which is that it is correct for programs to want to leak memory occasionally in this sense. I'll use the Z compiler itself as an example. So the Z compiler, when built in debug mode, will make sure to free everything. When built in release mode,
00:53:00
Speaker
it will not free once it's about to leave. It will not free memory once it's about to leave to close because the OS will clean up that memory anyway. And there's no point in freeing every single item that you've allocated if your program is about to exit.
00:53:18
Speaker
Making sure to free tiny things makes perfect sense when your program is going to use a ton of memory or it's going to be super long-lived. Otherwise, it's going to consume more and more memory over time until it eats all the available memory and everything explodes. But for, let's say, one-shot programs, kind of like a compiler, it's like you run utility, it runs to the end, and then it closes.
00:53:40
Speaker
cleaning stuff up at the end is just wasted time. Have you ever used Visual Studio? Not for so long. I can't believe. Thankfully, I haven't had to use it in a while now, but a few years ago, like seven years ago or something, I had to use it consistently. It drives me nuts that when you close it, not only it takes forever to load, that is already not okay.
00:54:09
Speaker
But when you close it, it takes forever to close. Why? Why is it taking forever to close? Because as it's closing, it's trying to free and run the destructors of every single component and sub-component and sub-sub-component. I have a vague memory of doing this with Eclipse and just getting into the habit of force quitting because who cares?
00:54:30
Speaker
Exactly, exactly. And Eclipse is another in Java. I think it's another language that has these factors and so kind of makes people want to use them a lot. But then there's moments where you actually really, in terms of functionality that you're offering to the user, you don't want to do it. You just want to close it right away. Long story short,
00:54:54
Speaker
I made this point because in reality, it is a legitimate behavior to have the program in specific circumstances, like memory, if you think about it. Because for real, the user experience would be genuinely significantly improved in both Eclipse and Visual Studio if the thing just exited right away. Of course, you do want to have a toggle, like a flag,
00:55:22
Speaker
they make sure you free all the memory cleanly so that you can guarantee that you do not have unwanted leaks. Visual Studio, for example, is a long-running program in Eclipse. So they should not be leaking memory in the normal operations. So you still want to be able to test for that.
00:55:44
Speaker
There are at least two memory management strategies. One is be very careful about what you're using because it's a limited resource. But for the long run, whatever memory you're using at the end, you can just drop on the floor. Exactly. Yeah, that makes perfect sense.
00:56:02
Speaker
There's one other big thing that you've talked about a little bit, but, um, I'm tempted to run over our usual time slots. I'm fascinated by this. Go for it. I, uh, I'm not in a rush for sure. Good. Okay. So comp time, you talked a bit about that. And as an old list programmer, this is a concept that makes sense to me, but I think it's never really gone mainstream. So why don't we talk a bit about the separation between runtime programs and compile time programs?
00:56:30
Speaker
Sure. So let me tell you about how Zig does this more specifically.

Enhancing Safety and Flexibility with Zig

00:56:39
Speaker
So comtime in Zig is interesting because Zig as a language doesn't have runtime type information. So for example, in JavaScript, Python, also in Go, you can ask questions to the program running at runtime about its types.
00:56:57
Speaker
C programs, on the other hand, don't have a runtime and they don't have runtime type information. Usually, it's not always the case, but usually runtime type information tends to go hand in hand with an actual runtime of the language. For example, in Python, you can create new types at runtime. You can do introspection. Having a runtime that can yield those dynamic properties to you,
00:57:26
Speaker
usually benefits from having runtime type information. C doesn't have those facilities, because a struct in C, at the end of the day, boils down to offsets in memory. Oh, the struct is, I don't know, 16 bytes long, and 8 bytes in, and it contains two fields. The first field is at offset zero, and the other one is at offset eight, and that's the end of it. So everything else has disappeared.
00:57:57
Speaker
But it is useful to be able to inspect types and reason about types, at least statically. So that's what Zig does. Zig does not give you runtime type information, but it does give you com-type type information. So you are not allowed, you're not able to create new types at runtime, but you are able to create new types at compile time
00:58:19
Speaker
by reasoning on other types. By the way, this is also what generic does in other languages. This is usually done in other imperative languages. This is usually done with a funky declarative syntax and a bunch of diamond brackets where you use diamond brackets to denote
00:58:39
Speaker
the generic type and then to put constraints on it using like some kind of declarative syntax. Like I want type T to be, I don't know, to conform to interface A or interface B, et cetera. Okay. So you're using, you're saying you're using comp time to do things like I want a list of A's, but now I need to pin it down to be a list of eight bit integers. Yeah.
00:59:06
Speaker
Because the idea is that you are creating a new type by referring to another existing type. And the way you do this in Zig is not via this custom syntax, but by using normal Zig syntax. So literally, a list, for example, let's say you want to make a generic list, and you want them to be able to make a list of integers, a list of characters, whatever.
00:59:32
Speaker
The way you implement this in Zig is that you create a function called list that accepts a type as input.
00:59:40
Speaker
which has to be marked as a comtime parameter. So the signature would literally read, fn list open parenthesis comtime t colon type. So it's a comtime parameter named t of type type. You have to pass in a type. And so that could be integer or whatever. And then this function returns another type.
01:00:03
Speaker
And in the function body, you create a struct, you return a struct definition that places, that defines the payload field, like a struct probably, that has the payload field of type T, what you passed in, which is kind of like generics work. But it's normal procedural zip code that gets executed compile time. So for example, you could create like an,
01:00:29
Speaker
Let's say you're making a simple array. But the length of that array, you want to be the result of other reasoning. You could create a Fibonacci function, write a comp time, and say that your array is long the 10th Fibonacci number, which I don't know how much it is, but it's not going to be 10. It's going to be a bigger number. So you can call a run normal z-code. It's going to be interpreted by the compiler
01:00:57
Speaker
while compiling. And usually, you do have some of that in other languages. It's just not fully general purpose. They give you restricted language to specify properties, and they have their own special rules. In Z, it's just you run the Z code. And the compiler has a concept of an execution quota, so that, for example, if you make a mistake and you try to make
01:01:23
Speaker
You make an array that is the 1,000 Fibonacci number, but your Fibonacci implementation is very bad. The compiler, after a while, is going to tell you, I executed 10,000 loops, and since we couldn't come to a conclusion, I gave up. And if you really think this is not an infinite loop, then you can pull up that number, the number of executions before giving up, and we're going to try again.
01:01:52
Speaker
But that way, basically, the compiler is how it deals with infinite loops and undecidable stuff. Yeah, so you're protecting people accidentally making compile time infinitely long. Exactly. And Alan Turing has opinions on why you can't automate that.
01:02:09
Speaker
Yeah, exactly. In our case, I think it's fine in practice to solve the indecidability problem by just giving up because ultimately, you're trying to compile a program and you're not willing to sit there forever or arbitrarily long to have it compiled.
01:02:27
Speaker
This raises two natural questions. The first has got to be, what's that like as a programmer? Most of us are used to using diamond brackets for generics. Do you prefer the Zigway? Does it feel natural once you get used to it?
01:02:44
Speaker
I think it feels insanely natural. You mentioned earlier Lisp. To me, by the way, I also love Lisp. I've never used Lisp professionally, but in university, definitely one of my favorite subjects. And I also loved writing macros in Lisp.
01:03:03
Speaker
And it feels like writing macros in Lisp. Or actually, I would say it's even better than writing macros in Lisp. Yeah, with a spicy opinion. So what I think happens with Lisp is that people say macros in Lisp are nice because Lisp is an homo-iconic language. So the language itself
01:03:26
Speaker
is the data structure that represents it. It's the list, the symbolic expression that represents it, which is fair. But I do think that the actual truth is that by having the program be a data structure,
01:03:47
Speaker
The language is steering you naturally towards treating the program as a data structure instead of it being a textual transformation.
01:03:59
Speaker
And in fact, you can write macros in lists that don't generalize really well, that make assumptions about a specific argument being or not being a list or being or not being quoted, for example.
01:04:15
Speaker
You are literally, comp time is more limited than what you can do with list macros, just to be clear. And that's also kind of by design. It's kind of like a 80-20 thing. It gives you 80% of the power, but it saves you from the 20% of really cursed stuff that people will want to do all the time. Or rather, with 20% of the complexity, which does save you from cursed stuff.
01:04:40
Speaker
In Zig, what you do is when you look at the type, you literally call a function, you call at type info, and you pass in a struct. So let's say that you made a struct named person, and person has age and name.
01:04:59
Speaker
And then you call type info on person, and what you get back is a data structure that contains... It's another struct that contains all the info about that type. Among other things, it will contain an array that contains the two fields with information about how the field is called, what's the type, etc., etc.
01:05:22
Speaker
And so your meta programming is always going to look at the program as data and never as syntax. And I think that's the key that makes come time weirdly, weirdly natural.
01:05:36
Speaker
Okay, yeah. Yeah, it does remind me, I mean, the frustration with Lisp macros was always that they were untyped and you could really cause things to explode in an even more spectacular way than normal Lisp. Absolutely. But the nice thing was that there was absolutely no difference between writing programs that worked compile time and runtime, because it was the same tools, same language, same everything.
01:05:58
Speaker
Exactly. And it's the same for Zig. Because you do use the same syntax. I have an example on a blog post that I wrote trying to introduce people to the concept of com-time. And my favorite example in there
01:06:14
Speaker
is this idea that, which is actually taken from real life experience. I was writing a Redis client for Zig. And in Redis, you have commands, like the query language of Redis makes you write commands that are case insensitive. So if you write it uppercase or lowercase, it doesn't matter. So at some point in my client, I wanted to recognize some of those commands. So I wanted to check for equality between two strings. And my idea was, well,
01:06:44
Speaker
to slightly, very slightly improve the performance of the comparison function. If I know that the constant string, like the string literal that I hardcode in my program that I used to check the user provided string against,
01:07:02
Speaker
If I know that that one is always going to be uppercase, I can simplify the comparison code ever so slightly. I can just remove one branch from the comparison. But now I want to enforce that when you call my equal function, the first argument that you're passing is always going to be uppercase.
01:07:28
Speaker
Right. So you want some compile time code to check those strings are correctly written. Exactly. Now, imagine trying to do that with diamond brackets stuff. I have no idea if you can actually even pull it off. Here's what you do in Zig. In Zig, in the function body, you open a comtime block. Well, first of all, you have to mark the first argument as always being available at comtime. So people will be forced to give you, it doesn't have to be a string literal directly. It can be like a variable name.
01:07:57
Speaker
But ultimately, the value containing that variable needs to be resolvable at comp time. It doesn't need to depend on weird stuff like the network. So you open a comp time block, and in there, you have a for loop.
01:08:15
Speaker
that loops over the string and checks that its character is in the correct range. That's it. That's all you do. Nothing weird. You just use the language to check the string character by character. And if you find a character that is not in your expected range, so in my case it was between uppercase A and uppercase Z,
01:08:34
Speaker
what you do is that you emit a compile error. And you can emit a compile error that says, well, you are supposed to give me an uppercase string and you didn't give me an uppercase string because this character is lowercase. You can even be precise and print the string and point out the specific character if you want. You can craft the message whichever way you want. And that becomes the compile error. And so now users of your API, not only the constraint is enforced, so if they give you a bad string, it will get a compile error.
01:09:04
Speaker
But the compiler error is also going to be designed by you. So people will get a nice compiler from the compiler that will tell them you're supposed to pass an application string, but you didn't. Nice. Yeah. So you can start doing bespoke compiler extensions and you don't have to learn a new language to do it. Nope. That's pretty sweet. Okay. Okay. That gives me a good sense of the footprint of the language.
01:09:30
Speaker
So there's one other big topic I think we should talk about, which is, I thought it was really interesting the way that the Zig project is funded, right? Because every language, particularly in every open source project, has a problem with getting enough work done because you've got to give up your day job if you really want a language to take off.
01:09:53
Speaker
And your approach, Zig's approach to funding is fairly novel. Tell me about that. So Zig is a 501c3 non-profit foundation, US non-profit foundation, like 501c3 is a thing in the US legal system. It's been kind of set up like a charity. Yeah, exactly what we normally would consider a charity.
01:10:20
Speaker
So it's tax exempt and you cannot pay dividends. So all the money that goes into the organization has to be used to pursue your mission. So basically you have to use the money to run the company. You can take it out and buy a yacht with it or whatever I mentioned.
01:10:42
Speaker
Ziggy is not the only language that has this legal structure. Python, I think it's also another 501c3, but not all languages are net. Some other languages are a different type of... It's still considered non-profit, but it's a different type of organization which does have to pay taxes.
01:11:01
Speaker
Usually, it's 501c6. It might seem that there's not much of a difference between 3 and 6, especially because it's a place where we normally, in semantic versioning, we would have the patch number. So you think, oh, c6, c3, whatever. They fix the bug in there. No, that's a huge difference.
01:11:23
Speaker
We're not always consistent with version numbers, but my god, lawyers, they can really change the rules between versions. So Zig specifically leaves mainly off of donations. So most of our income comes from people donating money to the foundation so that we can move forward with the development of Zig.
01:11:46
Speaker
Some money also comes from other things, so it's mainly donations from individuals. We do have also a good number of donations from companies, but I think in terms of if we were to do a pie chart and plot them both, they would, I think, roughly be balanced. So we do try actively to keep a balance between our sources of income.
01:12:13
Speaker
Because we don't want to get in a situation where one entity or a very small number of individuals end up having control basically over the foundation. Maybe not directly, not legally, but if they control the money flow, then ultimately they do control the destiny of the organization. And we do want to be able to say no to people.
01:12:33
Speaker
We do have support contracts, or rather we have one with Uber, because Uber is using Zig to cross-compile. They are cross-compiling, I think, as of today.
01:12:48
Speaker
all their backend services that require cross-compilation because of ARM servers mainly. So they wanted a while ago to be able to have ARM servers and not just Intel, well, XDD6.64. And so they use Zig and now they did the work to actually make sure that all their C and C++ stuff cross-compiles correctly.
01:13:13
Speaker
And yeah, so they have a support contract with us. But then again, it's not a huge chunk of our income.
01:13:21
Speaker
And that is mainly when it comes from income. So related to this, also, we kind of want to be independent. And we're very serious about this. We used to joke that... Because people sometimes say, oh, if you want your language to succeed, you cannot make a successful language unless you are supported by a big tech company.
01:13:48
Speaker
And we kind of beg to differ, but also our standard offer is how much money whatever big tech company wants to give us in exchange for 0% of the foundation and zero seats in the board of directors.
01:14:08
Speaker
But they do get Ziggy in the end, so they do get something in the end. Yeah, there is some quid pro quo, but no power. No power, no control at all. Zero, absolute zero. And because we really want to make sure that Ziggy is a BDFL run project, so also compared to other languages, we basically ultimately have Andrew, who is the creator, who acts as the ultimate
01:14:36
Speaker
It's not only him, there's a core team, there's people, there's a process which is also very public. You can read proposals to change the language on the GitHub and discussion happens in public and actually anybody can chime in. But for example, it's not a democratic process. If a feature proposal has a huge number of upvotes, that counts zero towards the decision of whether to include that feature or not in ZIG.
01:15:06
Speaker
Right. Yeah. That has some downsides, but usually has great upsides for design consistency. Absolutely. And it's absolutely, in my opinion, fundamental if you want to have your language stay small, if you don't want it to eventually devolve into a kitchen sink. Yeah, that's true.
01:15:27
Speaker
And there was a talk by the creator of the Elm programming language recently that I think dove into this general concept, I think, in a very nice way. Basically, I'm paraphrasing and I'm going to oversimplify.
01:15:40
Speaker
The talk is titled The Economics of Programming Languages, I think. It's from a strange loop. Well, it was given that strange loop. I highly recommend it, but the bit that I'm interested about was said something along the lines of
01:15:58
Speaker
Languages, there are 501c6s, more corporate languages that end up having a bunch of organizations come together into a consortium or a trade association. They basically look at the language as a marketplace. They look at the shared infrastructure and all the commerce, all the
01:16:23
Speaker
the business that this thing can support, which is reasonable, right? You look at a language like, I don't know, C sharp or Java, and those languages do enable a certain type of commerce. So from their perspective, they want the commerce to be as much as possible. They want to give the best market to their organization members. And so if an organization member wants something because it helps them do their business,
01:16:53
Speaker
you have a strong incentive to say yes. And whoever doesn't need that feature, they cannot use it, they can disable it. They don't have to use it, right? So there's no point in saying no to people if your goal is to enable the have the biggest possible market.
01:17:13
Speaker
But as the chronologies, we know that, well, there's some downsides from it, right? Once your language becomes a kitchen sink, then it's like, it's not good over time. So there's huge value in keeping your thing small and consistent. And I think that's what you get by choosing 501c3 over 501c6, or rather not going down the path of making your organization like a trade association.
01:17:38
Speaker
Yeah, it's interesting the thought that that one decision, how you're structured as a company or as a financial organization, will influence how you're designed as a language. Yeah, it has huge influence. People, programmers don't want to think about this stuff. They like to think, oh, I just want to focus on the code.
01:18:03
Speaker
It's a sentiment that I can understand. Frankly, I would like to only focus on the code. But the hard lesson that I learned is that to have the best technology, you have to get right the business side. The business side comes first. Every time you make a mistake there, the technology will suffer.
01:18:24
Speaker
In the long run, it really matters. In the short term, it doesn't. In the long run, it has a huge effect. That's true. I'm very glad we diverted into comp time, but we should probably wrap up and let the listeners go to runtime. How's that for a segue?
01:18:44
Speaker
If someone wants to get started with a SIG, I know you have LSP support, you have a VS Code plugin, you've got all the quality of life things for a new beginner, but where should they start learning?

Getting Started with Zig

01:18:55
Speaker
My recommendation would be go to the official website, ziglang.org, and there there's a learn section. The learn section has a guide on how to download Zig, install it, and it also links you to some learning resources. Personally, among those, the three main ones that I would suggest is as a starting point,
01:19:16
Speaker
the language reference, the documentation that tells you about the language, not the standard library. That one teaches you specifically about syntax of the language, and it's one page. It's one long page. It's not an A4 or US letter page, but it's just one page. It's not huge. And you don't have to read it all precisely. You can scroll through it. But that one gives you the baseline understanding of Zig.
01:19:45
Speaker
Then from there, I would suggest if you don't have experience with lower-level programming and you want a very smooth learning curve, Ziglings is the best starting point in my opinion. Ziglings is like a community project where basically you clone the repo and you get a collection of very tiny programs that don't compile or that don't behave correctly. In the comments, tell you how to fix them.
01:20:12
Speaker
So you go one by one and the comment will go, this program is supposed to print L award, but it doesn't. Fix it. And that's going to be super simple, right? You're going to just fix the string literal. But then going forward, the exercises will become very smoothly, but they will become harder and they will require you to understand more of the syntax. I think that's how I learned closure. They had a similar thing called, I think, the closure cones.
01:20:39
Speaker
It's like a series of small failing programs that you have to fix and you gradually learn the whole language. It's a lovely way to learn a new language. Yeah. Zigglings is very, very, very popular. I would say it's probably the most popular piece of educational content in the Ziggo system. The name Zigglings is also inspired by Rustlings, because Rust also has it, the same thing, and they call it Rustling.
01:21:07
Speaker
Nice, I will link to both of those in the show notes. But for now, Loris, thank you very much for joining us. It's a fascinating language with
01:21:19
Speaker
almost more scope than C, which I can't believe. It has pretty much all the scope of C. It tries to fix all the things that C for some reason never wanted to fix. Think about it. Why is Z able to cross-compile C and a C compiler is not going to be able to give you that out of the box? We didn't get into this, but you get a Z compiler and you write hello world in C and you can't compile it from Linux to Windows. Try to do the same with Clang. It's not going to work.
01:21:50
Speaker
I'm not even going to try. Yeah, but it's insane. So yeah, the scope is all of C, all of the things that C should have done that he didn't do, well, that's a little bit extra. Nice. That's enough to keep us busy for a while. Yeah. Loris, thank you very much for joining us. Thank you.
01:22:09
Speaker
Thank you, Loris. Since we recorded that conversation, I have been playing around with the Zigglings tutorial he mentioned, and yeah, I can confirm it's a nice way to learn. I'm also planning to find time to pull out my old Arduino microcontrollers, because I've dabbled with kind of embedded hardware in the past,
01:22:28
Speaker
I've never really been happy writing C. I've loved using Rust, but it's been a fight to get things to compile onto the embedded hardware. So hopefully, Zig is going to finally make me happy when I'm tinkering with soldering irons and wires and LEDs and stuff.
01:22:45
Speaker
In the meantime, I leave you with links to everything we've discussed. They're all in the show notes. There is a wealth of information out there about Zig, how to learn it, what it does, extra features we didn't get a chance to cover. And I'll leave you with a fun Easter egg. If you install Zig and type Zig Zen, it will tell you why it exists.
01:23:04
Speaker
I'll let you go and discover that. Before you go, please do take the time to give us a like or a share or a rate or a review. It is the easiest way to let us know which topics you find most interesting so we can do more episodes on those kinds of topics. And if you haven't already, click subscribe or follow to catch future episodes. And until the next episode, I've been your host, Chris Jenkins. This has been Developer Voices with Loris Crow. Thanks for listening.