
Interview with Zig language creator Andrew Kelley [video] - jorangreef
https://www.youtube.com/watch?v=ZvskDoP09Ao&feature=emb_logo
======
logicchains
I work in HFT, and one of the key concerns when writing low-latency code is
"is this code allocating memory, and if so, how can I stop it?" Zig is the
perfect language for this use case as none of the standard library implicitly
allocates, rather for anything that allocates, the caller must pass in an
allocator. The stdlib also provides a handy arena allocator, which is often
the best choice.

This is a huge advantage over C++ and Rust, because it makes it much harder
for e.g. the intern to write code that repeatedly creates a vector or
dynamically allocated string in a loop. Or to use something like
std::unordered_map or std::deque that allocates wantonly.

~~~
the_duke
There is some ongoing work towards custom allocators for containers in Rust
std. [1]

Right now you could also go no_std (you still get the core library, which does
not contain any allocating data structures) and use custom containers with a
passed in allocator.

Zig is definitely a cool language, and it will be interesting if they can come
up with good solutions to memory management!

But sentences like these in the documentation [2] would make me prefer Rust
for most low level domains (for now):

> It is the Zig programmer's responsibility to ensure that a pointer is not
> accessed when the memory pointed to is no longer available. Note that a
> slice is a form of pointer, in that it references other memory. ...

> ... the documentation for the function should explain who "owns" the pointer

[1] [https://github.com/rust-lang/wg-allocators](https://github.com/rust-
lang/wg-allocators)

[2] [https://ziglang.org/documentation/master/#toc-Lifetime-
and-O...](https://ziglang.org/documentation/master/#toc-Lifetime-and-
Ownership)

~~~
pron
> But sentences like these in the documentation [2] would make me prefer Rust
> for most low level domains

While such use-after-free issues are not prevented at compile time, the plan
is to ultimately have safe Zig catch them (and panic) at runtime, i.e. safe
Zig shouldn't have undefined behaviour. Because this is done with runtime
checks, the expectation is that those checks will be turned off (selectively,
perhaps) in production, after testing has satisfied you. In that case, the
guarantees aren't as strong as Rusts, but those guarantees come at a
significant cost -- to language complexity and compilation time -- that can
also have a negative effect on correctness. So while Zig's approach to
safety/correctness is certainly very different from Rust's, I don't think it
is necessarily weaker (perhaps it could even be stronger, but the question is
hard to settle).

~~~
aw1621107
> but those guarantees come at a significant cost -- to language complexity
> and compilation time

Aren't Rust's compilation time woes more due to the amount of IR the
front/middle-end give to LLVM? I was under the impression that the type
system-related stuff isn't _that_ expensive.

~~~
littlestymaar
The borrow-checking and ownership mechanism is cheap, and it's almost never a
significant part of the big compilation time encountered in Rust.

What's not cheap, and is responsible for long compilation times (the order is
arbitrary, the relative weights are highly dependent of the code-base):

\- size of the code generation units (the whole crate vs individual files in
C)

\- procedural macros

\- generics & traits

\- interaction between generics & LLVM IR generation (a lot of bloat is
created, to be removed by LLVM later)

\- LLVM itself

Most of those are being worked on, but in the end it's mostly a _social_
problem: as Rust users are used to long compile time, many of them don't
especially take care of it, and most gains in the compiler are often
outweighed by people writing slower code. It's already possible to write Rust
code that compiles quickly, _if you pay attention_. The culture is evolving
though, and more and more library authors are now mindful of compilation time
of their crate (and the tooling to diagnose it is also improving).

Key takeaway: Memory safety isn't what makes Rust compile slowly, “zero-cost
abstractions” is.

~~~
pjmlp
With C++ I can get zero cost abstractions without Rust like compilation times,
in spite C++ fame of slow compile times.

How?

By making heavy use of binary third party dependencies, every module gets its
own binary library, no crazy use of metaprogramming, incremental compilation
and linking.

My WinUI/UWP professional work compile in a fraction of my Gtk-rs toy
applications.

I keep measuring improvements in this area, and hopefully Microsoft's own pain
with Rust/WinRT might trigger some improvements.

~~~
littlestymaar
> By making heavy use of binary third party dependencies

I use Rust because I need performance, then I compile my Rust code for the
exact CPU instructions available on my target machine and with PGO, binary
dependencies can't do that.

Also, binary third party come with a lot of hassle (compiler version & options
used can break your build) so I'm really glad Rust took the source-code
dependency route instead (at least by default).

You can use binary dependencies though, as long as you compile everything with
the same compiler it will works.

~~~
pjmlp
Except that doesn't work for the business of selling binary libraries for
mobile and mainstream desktop OSes.

The only hassle is not wanting to learn how to use compiled languages
properly, that is how we end up with the brain dead idea of header only
libraries.

Regarding performance, Rust still needs to catch up with C++ in many domains.

There are plenty of reasons why C++ is my to go language outside my managed
language options, despite my appreciation for Rust, and C++'s caveats of copy-
paste compatibility with C.

------
pron
I think that Zig's simplicity hides how revolutionary it is, both in design
and in potential. It reminded me of my impression of Scheme when I first
learned it over twenty years ago. You can learn the language in a day, but it
takes a while to realize how exceptionally powerful it is. But it's not just
its radical design that's interesting from an academic perspective; I also
think that its practical goals align with mine. My primary programming
language these days is C++, and Zig is the first low-level language that
attempts to address all of the three main problems I see with it: language
complexity, compilation speed, and safety.

In particular, it has two truly remarkable features that no other well-known
low-level language -- C, C++, Ada, and Rust -- have or can ever have: lack of
macros and lack of generics (and the associated concepts/typeclasses) [1].
These are very important features because they have a big impact on language
complexity. Despite these features, Zig can do virtually everything those
languages do with macros [2] and/or generics (including concepts/typeclasses),
and with the same level of compile-time type safety and performance: their
uses become natural applications of Zig's "superfeature" \-- comptime.

Other languages -- like Nim, D, C++ and Rust also have a feature similar to
Zig's comptime or are gradually getting there -- but what Zig noticed was that
this _simple_ feature makes several other complex and/or potentially harmful
features redundant. Antoine de Saint-Exupery said that "perfection is
achieved, not when there is nothing more to add, but when there is nothing
left to take away." I think that Zig, like Scheme -- and yes, there are others
-- is close to that minimalist vision of perfection.

What a truly inspiring language. Rather than asking how we could make C++'s
general philosophy work better as another increasingly famous language does,
IMO, it asks how we could reshape low-level programming in a way that's a more
radical break with the past. I think it's a better question to ask. Now all
there's left to hope for is that Zig gets to 1.0 and gains some traction. I,
for one, would love to find a suitable alternative to C++, and I believe Zig
is the first language that could achieve that in a way that suits my
particular taste.

[1]: I guess C has the second feature, but it loses both expressivity and
performance because of it.

[2]: Without the less desirable things people can do with macros.

~~~
littlestymaar
> What a truly inspiring language

It's indeed an inspiring language, and rust is taking inspiration from it
already: [https://github.com/jswrenn/project-safe-
transmute/blob/rfc/r...](https://github.com/jswrenn/project-safe-
transmute/blob/rfc/rfcs/0000-safe-transmute.md#safe-transmute-rfc)

> lack of generics

I can't wait before Zig2 comes and eventually adds generics…

~~~
pron
> and rust is taking inspiration from it already

But C++/Rust can never have Zig's primary feature -- simplicity. Zig's power
is not that it _has_ comptime, but that it has little _else_.

> I can't wait before Zig2 comes and eventually adds generics…

No need. Zig gives you the same capabilities as generics do, only through a
separate feature that other languages also have in addition to generics. In
other words, it has generics, but without having generics as a special
construct. Zig recognises that once you have that other feature (compile-time
introspection) you don't need generics as a separate construct, but they can
be just an instance of that single construct.

~~~
littlestymaar
> But C++/Rust can never have Zig's primary feature -- simplicity

Sounds like a Go pitch, except Zig ain't Go. And while comptime is a cool
feature, it's also a really complex one!

> In other words, it has generics, but without having generics as a special
> construct. Zig recognises that once you have that other feature (compile-
> time introspection) you don't need generics as a separate construct, but
> they can be just an instance of that single construct.

This has advantages (only one feature to know), but it also has a big
drawback: the lack of orthogonality. C is also simple, for instance it has no
concept of errors (only return values) or arrays (only pointers), but most
people won't consider this a good idea (and Zig didn't follow C on either of
those two design points)

Zig is cool, but I hoped the “generics are too complex of a feature” meme
would die now that Go is getting generics, and I'd be really sad to see come
back…

~~~
pron
> it's also a really complex one!

No, it's a very simple one, so much so that it's erasable:
[https://news.ycombinator.com/item?id=24293611](https://news.ycombinator.com/item?id=24293611)
And still it is probably the most complex aspect of Zig.

> Zig is cool, but I hoped the “generics are too complex of a feature” meme
> would die now that Go is getting generics, and I'd be really sad to see come
> back…

You've misunderstood me. Generics are a good thing -- if that's all you have.
But if you have generics _and_ procedural macros, it turns out that you can do
the work of both with a feature that's simpler than either. The capability
generics add is a very important one, but given that low-level languages need
another one as well, it turns out that generics can be subsumed into that one
without being a _separate_ and _additional_ construct. Zig has generic types
and concepts/typeclasses; these just aren't atomic language constructs.

~~~
littlestymaar
> But if you have generics and procedural macros, it turns out that you can do
> the work of both with a feature that's simpler than either.

Here I think we just have a different subjective perception of what simplicity
is. I much prefer have two orthogonal systems which do their own business than
having a single more powerful tool than do both (like having slices +
references instead of the all powerful pointer)

Anecdotal note: more than 10 years ago, the Go team pitched why they didn't
need generics nor macros, because code generation would solve both problems (+
others), and now they're on their way back to add generics to Go (with a lot
of hassle).

~~~
pron
> I much prefer have two orthogonal systems which do their own business than
> having a single more powerful tool than do both (like having slices +
> references instead of the all powerful pointer)

OK, but that's not quite the situation. Here we're talking about languages
that have, or will have, the single "more powerful" construct, _and also_ the
more specific, special case one, as two separate constructs, even though one
of them would have sufficed.

Again, Zig has parameterized types, and very elegant and powerful ones --
they're functions that take some types as argument and return a type. It just
doesn't have generics as a separate construct. Rather, it is a special case of
a more general one (that Rust and C++ will also have).

------
tobz1000
Some of Zig's ideas fascinate me, both the great low-level concepts (e.g.
arbitrary-sized ints), but much more than that, the high level concepts.

Particularly great is Zig's handling of both macros and generic types, the
answer to both of which seems to be: just evaluate them at compile-time with
regular functions, no special DSL or extra syntax. Andrew mentions in the
video a big drawback of this system - implications for IDE complexity and
performance. I imagine the performance side of this could be (maybe is?)
mitigated by limiting recursion depth/loop counts for compile-time work.

I'm not particularly interested in taking on a language with manual memory
management and the responsibilities it entails, but I would love to have
access to Zig's compile-time capabilities, if it were available with some more
memory safety.

~~~
pron
Zig gives you memory safety (or, rather, will ultimately do that), but it does
so in a way that's different from both languages with garbage collection
(whether tracing or reference-counting) or with sound type-system guarantees
a-la Rust. It does so with runtime checks that are turned on in development
and testing and turned off -- either globally or per code unit -- in
production. You lose soundness, but we don't have sound guarantees for
functional correctness, anyway, and given that Zig makes testing very easy,
it's unclear whether a particular approach dominates the other in terms of
correctness.

~~~
TinkersW
That is the same approach used in many C++ projects

~~~
pron
But to do that you can only use a subset of C++ (e.g. you can't use arrays nor
pointer arithmetic). This works for all of Zig, except for some very specific,
clearly marked, "unsafe" operations.

~~~
TinkersW
It works with arrays if you stick with std::array & std::span like constructs.

It also works with iterators-generally by sticking some extra data in the
iterator in dev builds, so it can check for out of bounds access.

If I do have some code that uses C pointers + size, I'll insert some dev build
assertions.

~~~
pron
Sure, and then when you enforce that you address the third most bothersome
thing for me in C++, leaving you only with the top two (for me): a complex
language and slow compilation.

------
HourglassFR
I've stumbled upon the Zig language a while back and have been checking in
regularly to follow its progress. Recently I took the time to write a very
small program to get a feeling for it. My thoughts :

\- It's a very low level language. Having written mostly Python for the past
few years, it is quite the contrast. I had to force myself to think in C to
get the train going

\- Getting my head around the error handling took more time than I'm willing
to admit. In the end, it's like having exception but being more explicit about
it. It feels nice when you get the hang of it

\- The documentation of the standard library is severly lacking, to be fair
the language is still very young. More worrysome, it feels very cluncky.

\- No proper string support. It is sad that a modern language still goes down
that route after Python has shown that correcting this is both definitely
worthwhile and a word of pain.

\- I have the feeling that optional and error union types are a bit redundant,
but I have not written enough Zig to have a real intuition on that. Maybe it
is just that I understand monads now.

~~~
AnIdiotOnTheNet
Standard library documentation is indeed clunky as it is auto-generated for
the most part. This is something the community has been working on improving
but it isn't a priority at this stage in part because the standard library
undergoes breaking changes pretty frequently right now.

Optional and ErrorUnion are a tiny bit redundant in that one could represent
the Optional as another value in an ErrorUnion, and that might even happen as
an optimization step in the case of ?!/!? types at some point in the future,
but they have very different handling in the language as they are used for
very different things.

I personally like that Zig doesn't bother with "strings" at a language level
at all and just considers everything as arrays of bytes. String handling is a
complexity nightmare and I feel that Zig wisely chooses to be simple instead.

~~~
HourglassFR
> Standard library documentation is indeed clunky as it is auto-generated for
> the most part.

I have not expressed myself clearly: the auto-generated documentation is
severly lacking. The API of the standard library is clunky. To be fair, both
those points are getting better. And yes, the language is very young and I
understand that there are more pressing issues with the core language itself.

> I personally like that Zig doesn't bother with "strings" at a language level
> at all and just considers everything as arrays of bytes. String handling is
> a complexity nightmare and I feel that Zig wisely chooses to be simple
> instead.

It is definitely simpler, alas not everything is ASCII and arguing it should
be to make life easy for programers is hardly a reasonable stance.

Also, maybe it is not clear in my comments but I actually enjoy Zig.

------
kristoff_it
Just as a reminder, the Zig Software Foundation (501c3 non-profit) is looking
for donations in order to be able to pay developers working on the compiler.

[https://github.com/sponsors/ziglang](https://github.com/sponsors/ziglang)

------
rvz
At least its C FFI bindings story is much more pleasant than Rust's
complicated swiss army knife of toggles and flags in bindgen.

The Rustaceans should be taking notes on this.

~~~
kreco
Yeah, that's actually how any C FFI bindings should be.

Ans also, that's the strength of C and its simple ABI.

------
andi999
What is the best way to start with zig, if you know C by heart? I had a look a
while ago, but I feel I miss out how the concepts are to be used in practice.

~~~
kristoff_it
If you want to be eased into the language, start by checking out
[https://ziglearn.org](https://ziglearn.org). Otherwise just take a look at
the overview on the homepage of [https://ziglang.org](https://ziglang.org),
then the docs.

After that you should already be in great shape and you can read the standard
library for examples of useful patterns.

~~~
Oreb
Is the [https://ziglearn.org](https://ziglearn.org) site up to date with the
latest versions of the language and standard library? The initial "Hello,
World" example fails to compile for me. I get:

Semantic Analysis [533/803] ./main.zig:4:14: error: container 'std.debug' has
no member called 'print' std.debug.print("Hello, {}!\n", .{"World"});

~~~
pfg_
It's the opposite - you have version 0.6.0, but the hello world there is for
the latest master version of zig which can be downloaded at
[https://ziglang.org/download](https://ziglang.org/download)

------
lokl
Zig is appealing to me, but I wonder whether time spent mastering Zig would be
better spent mastering C.

~~~
jorangreef
The first rule of C is that no one masters C, but you could try anyway and
still have time to master Zig in a matter of weeks, which is a rounding error.
Given that both offer a C compatible ABI, what would serve your projects
better?

~~~
cmrdporcupine
<rant-time>

I can't help but feel like in our industry C is successful (vs its 80s
competition of Pascal/Modula-2, or Ada etc.) partially because of some of the
same reasons that Git is successful now. Yes, it is powerful and flexible; but
also in some ways unnecessarily arcane and 'dangerous' and _this gives the
user a feeling of cleverness_ that is seductive to software engineers.

Put another way: Most of us enjoy the mental stimulation of programming, and
we enjoy the mental challenges (in general). C makes us feel clever. Witness
the "obfuscated C programming contest" etc.

Same thing that has led to nonsense 'brain teaser' whiteboard-algorithm tests
at job interviews. IMHO it's in many cases for the benefit of the
interviewer's ego, not the company or the interviewee ("gotcha! no job for
you!").

</>

~~~
jorangreef
"Put another way: Most of us enjoy the mental stimulation of programming, and
we enjoy the mental challenges (in general). C makes us feel clever. Witness
the "obfuscated C programming contest" etc."

Yep, only C makes me feel stupid (but I enjoy that experience too!).

~~~
cmrdporcupine
Oh don't get me wrong, I'm a philosophy major drop-out, not a CS student. :-)
I have never gotten off on clever-C, and it makes me feel stupid, which yeah,
isn't awful either (humbling).

Luckily my day-job has nothing to do with mental gymnastics even though I'm a
software engineer at Google and work in plenty of low-level stuff. Most
sensible software development bears little resemblance to the stuff on
whiteboards in coding interviews etc.

After 20 years of this I know the right thing is to reach for a library, and
if that doesn't exist, then reach for Knuth or some other reference rather
than try to write it myself from scratch.

------
Kednicma
I hope that we're not stuck writing piles of low-level code for all eternity.
We don't need more than a few pages of each low-level language, and while I do
really like Zig's qualities compared to C, I'd still like to minimize the
amount of Zig or C total that has to be written.

I think that our community's equivalent of "where's my flying car?" is
"where's my higher-level language?"

~~~
pron
Who's the "we" who are "stuck"? The vast majority of programmers don't use
low-level languages for writing applications even today, but there is a big
niche of domains where close to perfect control is needed and that's the
domain low level languages like C, C++, Ada, Rust and Zig try to address. I
wouldn't (and don't) write "ordinary" applications in those languages, but I
don't think the domains they target will ever go away or become less
important.

~~~
notacoward
> The vast majority of programmers don't use low-level languages for writing
> applications

I work in a multi-million-line codebase, a significant majority of which is
very far from that "need perfect control" domain but is written in a what I'd
call a mid-level language - a high-abstraction dialect of C++. So I'd say GP
is correct, that too many people are stuck writing code in the wrong language
for the task at hand. The need for languages like Zig to improve the lower-
level experience (which, as you say, is not going away) and the need for
higher-level languages for more common types of programs are not in conflict.
They're complementary. It's the mid-level languages that need to DIAF, because
they're not really suited for either and pretending to be more general than
they are only encourages people to make choices that hurt them.

~~~
pron
I totally agree, and I think that C++ is exactly this "wrong kind of
language," and Rust follows in its footsteps, but I'm sure others disagree.
For example, for decades Microsoft has shown an attraction to this kind of
languages (they love C++, C# is going down that path, and they're showing
interest in Rust), so it might ultimately be a matter of taste -- a personal
aesthetic preference -- unless somebody is ever able to make some empirical
observations that show an objective benefit to one approach over another.

~~~
int_19h
How is C# similar to C++ in that regard? It's a much higher-level language.

