The State of Zig and Advocating for New Languages

Recently, we’ve experienced a few changes that have sparked conversation and controversy about design choices and the state of Zig. I wanted to create this thread so people can voice their thoughts on the state of the project.

First, there’s a recurring theme lurking in these topics that seems to find it’s way back to the surface and I think it’s good to talk about that issue directly.


  • Zig is not version 1.0 yet

This point has been brought up on several occasions to remind users that major changes are ongoing. For some, this is a reasonable response that speaks to rationality and temperament towards change. For others, it seems like an excuse for loading in features that seem misleading or obfuscating. I’d like to start by exploring the pros and cons of this response.

Pros:

It’s technically true. The language has not reached the version of 1.0 and is still under heavy development.

The benefit of this attitude is that it encourages us not to be weighed down by the baggage of day-zero design philosophies and choices. There are many language choices (such as nullptr) that people wish they could go back in time and change.

Keeping your expectations realistic is important for developing languages because it enables you to measure the magnitude of project that is appropriate for this stage of development. An interesting post that I saw from @kristoff in a recent discussion was as follows:

In that post, @kristoff also made some practical advisements for users that want to introduce Zig into their company ecosystem (it’s worth a read).

Cons:

Let’s start with the observation that 1.0 is just a number. Yes, it’s important as far as numbers go, but it isn’t a magical assignment.

Take C++ for example - it was invented in 1979 but templates were introduced ten years later in 1989. There were even books published like “C++ Templates: The Complete Guide” in 2002 when in the year 2020 there were template features added that radically changed the language again via the expansion of non-type template parameters (NTTP).

The stance that I believe can be derived from this observation is one that pays unique attention to the gradient of change. In other words, each version is important and 1.0 is just another version. In fact, a more radical view could be that how we get there is the most important aspect.


At this point, I’d like to hear from you. What are your experiences working with developing languages and/or advocating for specific languages to be used?

When is the right time to advocate for the usage of a language? Should we wait or try to get people on board early?

What do you think about the development of languages - what does “1.0” mean to you?

Thanks :slight_smile:

12 Likes

Here’s a motivating example - var never mutated became an error very recently. Some people think that the original behavior should have been kept in tact with opt-in capability, while others thought that we need to change this now before this issue becomes common practice.

Another example came up regarding fixing bugs in the compiler for the sake of correctness or for what is the common use case where incentive is higher.

2 Likes

There is no calibrated definition of stability for languages that are version < 1.0. Even official stable languages can evolve fast. Rust, for example, releases new version on time schedule every 6 weeks while being > 1.0.

For me, maturity of the language, never mind it being actively developed, is indicated by maturity, size and complexity of its “killer applications”. And Zig is doing quite well in this area. Zig compiler is probably the most complex project implemented in Zig. Then there are tigerbeetle database, bun nodejs killer, ghostty terminal (still in private beta but progressing by leaps and bounds). Compared to similar upstarts like Nim or Odin, Zig seems to have more “mature applications”.

1 Like

That’s definitely one aspect that’s important - the actual code that’s written in a language definitely helps define what a language actually is and does. Without it, it’s hard to see that language as anything other than purely academic or experimental.

I think the thing people are bothered by (and what I would add to your definition of maturity so far) is backwards compatibility. This is very important for a few reasons…

First, if I want to hire developers for a job, I want to know that there is a talent pool surrounding the language that’s viable. I see this with C++ developers quite often who write code the same way they did in the 90s. Basically, this means that I have a pool of people who can write in the language and be competently replaced should they decide to leave.

This problem is no better when we include AI - do I have to retrain all my models every time a new version is released and does that lead to stable generative behavior? In fact, it’s worse with AI because there may not be enough training data in the new way of doing things to assemble a robust training set.

And of course, there’s the issue of being left on a technological island. Backwards compatibility also means that there’s a chance to evolve my project to better standards without having to rewrite the entire thing completely. I’ve seen 30 year old projects move to more advanced compilers (with great effort, of course) because the old stuff still ran after being built.

This relates to the 1.0 conversation because I think there is an implicit belief forming that the language will not change as much or “certain things” once it hits that point.

One important question to ask about any language (or library, framework, etc.) is whether you trust the direction and vision of the project and the people leading it, and this is especially important for a language which is not yet stable. For example, consider the issue of Zig (eventually) moving away from LLVM: the difference between “this is going to be the death of the language” and “this is an exciting change and I’m hopeful to see it happen” is whether you trust that Andrew and the rest of the core team will make sure that Zig will continue to serve its users, including those using C and C++ in their projects.

This is something that can only really be seen once a project has been going for some time, which is part of why I think many people are hesitant to become very early adopters of new technologies, but I think by now Zig has had enough time to demonstrate that 1. it’s not going to pack up and disappear overnight, leaving its users stranded and 2. it’s not going to make decisions that alienate its users or its ideals. It might break users’ code (and often does, as seen recently), but never without consideration for how it affects them and the direction of the project.

And this is even relevant for “stable” languages: without being able to trust the project’s leadership, there’s no guarantee that their vision of what “stable” means will match what their users expect, or that they won’t turn around and release a “2.0” a few months later, or that they won’t make some other decision that ends up hurting broader adoption and continued use.

6 Likes

Again taking a page from the Rust playbook, one can define “editions”. So far Rust has had 2015, 2018 and 2021 editions. They are not backwards compatible with each other but Rust compiler supports them all. As a result, for a programmer Rust code appears to be backwards compatible.

5 Likes

not to be confused with a “Basic” method and thinking like 30 years ago, writing “meta” is not always justified.

Before making C better with ZIG, I’m thinking of trying to use “ZIG”

but 30 years ago, we counted the dicks and we managed to create management programs, for example billing in 24kb and we ran overlay in total a channel which reached 10 MB was colossal, today 400 MB and I am far from generous.

The analysis and methods were scrupulously studied.

For me, it’s not the code or its small variants that change over time that bothers me, but rather how to manage memory and purge it in its details and with complex examples.

1 Like

The Allure of 1.0

There’s the expectation that when you reach 1.0, you can really join the party. The big companies will use your language and start throwing cash at you via contracts. The big projects will start using your language and promote you with their users. The big authors will start writing books about your language. People will feel safe using your language. etc…

The Pain of 1.0

You must never break existing user code (unless it’s a critical vulnerability with no other alternative).


I think that the Zig project has made an extremely wise decision in not rushing to 1.0. A long pre-1.0 period is proving to be a very fertile ground for experimentation and fearless trial-and-error regarding language design and implementation. It’s precisely the ability to break existing user code that allows the Zig project to evolve in ways that other languages can’t, having sealed their fate by reaching 1.0.

And as @slonik-az mentions regarding Rust’s Editions, I think that’s a really good technique to allow a language to further evolve even after the 1.0 milestone. It’s really impressive how Rust can even handle crates from different Editions in the same project, allowing for a gradual upgrade path.

8 Likes

The way you earn trust is by treating people with respect. Observe the Golden Rule. Don’t insist on flexibility while denying flexibility to others. If the language itself isn’t finalized, then controversial design decisions like those concerning unused/unmutated variables need not be finalized either. Options should be available to users at this stage, with the understanding that compiler behavior will become fixed one way or the other when the time comes for the big one O. These options only exist so features can be tested in the real world. So users can vote with their feet.

I envision a system like this: By default, the compiler will complain about unused/unmutated variables. It will not respond to any flag. People who dislike this behavior can place a prerelease.conf at the root of their git repo to switch to one of two alternate implementations: reporting based on debug/release (my own preference) or reporting based on a --strict flag. Some time down the line we then scan Github for Zig projects. If the majority programmers choose to program with reporting off, then the claim of bug reduction is clearly not borne out and the default should this be changed.

3 Likes

Controversial is in the eye of beholder. For a long time Zig have been generating errors for unused variables. And we all learned to put _ = x; in the code and zls learned to help us with that. No controversy here. Unmutated variable error is a logical extension of the same and we learn to put _ = &x; and zls will help us here the same way.

3 Likes

Speaking of controversial decisions. Zig is moving at full speed to get rid of LLVM. Andrew explained very eloquently what are the problems with LLVM and the benefits of having Zig’s own back-end compiler chain.

I would like to understand why Rust is not ditching LLVM. They are suffering the same way from the same problems. Rust compilation is slow, getting LLVM people to fix bugs is hard, and so on. Yet, they are staying with LLVM despite having at least an order of magnitude more people on the development team that can pick up the task.

But you never know until you try. May be in Zig world one can replace LLVM easier than in the Rust world. May be it is like Lua vs Python. Something that takes an army of Python hackers is done by two guys in San Paolo in their spare time. :grinning:

1 Like

The stage2 zig compiler has been designed over the last many years with support for different backends being one of the main goals. So of course it will be easier to ditch llvm.
I don’t know much about development on the rust language, but I’d guess that the compiler isn’t designed to support anything other than llvm. They’d probably need to rewrite the entire thing to get rid of llvm.

4 Likes

Actually besides llvm Rust compiler supports wasm.

“Controversial” literally means giving rise or likely to give rise to controversy or public disagreement. The fact that not everyone (even in this very forum) agrees on the desirability of these features means there is a controversy.

What’s most disheartening to me personally is this push to saying “there is no discussion to be had”. I am willing to accept @andrewrk 's choice on this, but whatever choice is made, it does not mean that everybody agrees.

9 Likes

In an ideal world… If the software is working for how you need to use it, then it should be ready for production. The majority of security and stability issues would be from the standpoint of the compiler as opposed to the network, so a lot of those problems would reflect the strength of your tests. Also just because a new version of Zig is out, doesnt mean 100% you have to upgrade to it. If you can handle adjusting to breaking changes appropriately, then the end user shouldnt notice the difference. Maybe it’s running a little faster or slower, but the consequences would depend on the situation, and how well you can adapt.

My humble opinion 1.0 is fundamentally just another stepping stone, albeit more significant.

As a newcomer to the language, I don’t have a lot of Zig-specific thoughts other than to say that I really think the community is doing a lot of things right.

But as someone who has been in the Raku community for a decade, I have a few thoughts on these questions.

A wizard is never late, nor is he early.

With a sufficiently ambitious goalset, 1.0 can take a long time. For Raku (or Perl 6 as it was known back then), that long time was 15 years and arguably we still released too soon. There was a feeling in the community that a release was necessary partially just to shut down the “Duke Nukem Forever of progamming language” naysayers. Combine that with a hard target of Christmas (any Christmas) and we shipped a 1.0 that required several small-but-fundamental fixes shortly thereafter.

You don’t get that first impression back

Zig is really lucky because in that it doesn’t need to achieve the entirety of its sufficiently ambitious goalset in order to deliver a 1.0. Because part of the goalset is a replacement for LLVM, this effort can theoretically be developed outside of the 1.0 timeline.

The right time to arrive with a 1.0 should be somewhere after the moment that the standard library is concrete enough such that someone with a good judgment for the task has deemed it reasonable to fully document the stdlib and that work has been done.

It’s worth focusing on excellent onboarding.

Concrete guidelines for what needs to be done for 1.0 could help distribute the effort and build momentum. Even the discussion surrounding those guidelines would help to clarify and consider what is “1.0 worthy” and what can reasonably be set back into the future.

Regarding evangelization, I think that the Zig community does a decent job of this already. I expect that there is a sweet spot of when to push people to try it – it’s both hard and necessary to get people to use alphas, betas, and release candidates.

Getting new users on board and excited early in the leadup to 1.0 could involve all sorts of techniques (gamifying the contribution process to 1.0 in non-gross ways is one option), but the strongest argument for joining Zig’s 1.0-and-beyond efforts will probably always come from the force of the software written in it.

8 Likes

You know what has been happening for a long time? People programming in C. We have all learned to deal with that language’s idiosyncrasies. There are thousands upon thousands of tools out there that help us deal with them. Now why should any C programmer give Zig a chance if your argument were valid?

As I said, observe the Golden Rule. Telling people to go pound sand i"this is how’s things have always been done!" is a super duper lousy way of advocating for a new language.

3 Likes

Yep, software speaks for itself. Release 1.0 is overrated. It is just a big milestone, the language and stdlib will not be complete by that time and will still require work. But if some smart people voluntarily chose Zig for their non-trivial projects and delivered – this speaks more about the state of the language than its semantic versioning tag.

For me it is comptime. This is a giant leap over C and any other language playing in this league.

I think one important part about the language its developmental direction and advocating for its use, is simply to just chill and not get too emotionally attached to one outcome over another.

While everyone has their particular set of priorities and ideas about what is important and where the journey should go, one project can’t follow every possible route.
There are different ways that journey can be taken, Zig has chosen to go the BDFL way of making decisions, personally I am glad, because while I might sometimes have ideas where I would prefer some popular solution to become the chosen solution, overall I am not aware of a programming language that was design by committee, that I actually enjoy using.
IMHO I would rather live with some design choices I might not have chosen, then end up with a Frankenstein language monster, where there was never a single language designer that had a compelling and coherent vision for where the language should be going.

So at an abstract level it seems to me every language has a limit to the amount of differing directions it can reasonably support and thus also the range of people who will be satisfied by what the language offers. The part that is interesting about Zig to me is, that it doesn’t just say “here is what you get and that’s it, if you don’t like it get lost”, instead I get this sense instead “here is what we do to achieve X, Y, Z and this enables these core features and a stable foundation to build on, with that foundation we can support new projects and these new projects will be able to help you achieve other things we can’t easily support directly”.

One concrete example for that is other programming language communities using zig as a cross compiler, in that sense zig already makes go or rust better for some users of those languages that have other priorities.
Maybe it is time we stopped having language wars and language design wars and had language collaborations instead (and with that I don’t really mean that we should vote on everything, because I think that is lacking in terms of practicality and getting things moving forward), I mean it more in terms of everyone pondering “maybe the thing that is so important to me is also important to others, but there also might be good reasons why it isn’t priority right now and maybe sometimes some things might find their solution some other time some other way, or might even be difficult to explain without providing a whole large essay of other difficult to explain things”.

While I can understand wanting an explanation, that also has a cost, instead trusting someone to come up with something, gives that person room to breath, to actually come up with something, instead of being distracted with justifying their work, while they are working on it. (Which might lead to burnout if there is too much of the latter)

I have only read a handful of Zig issues, and often times I felt an overwhelming amount of details and tradeoffs looking on the presented options and problems, I simply can’t make a judgement on what feature solves problems and which ones create a lot of new ones, I think it is easy to overestimate the importance of something that annoys you today, over something that might be created to fix that annoyance, creating other annoyances, that may persist for years and might not be discovered until it is already difficult to change.

Going slowly, not making the language too cute (making the language superficially more easy to use, by creating other more hidden complexities), taking time to get to 1.0 are good things. Whether we like it or not 1.0 will be perceived by a lot of people as an important milestone, so taking your time to get there, is in my opinion better than getting there fast, which generates artificial hype.

Personally I think Zig staying a small not overly complex language with clear design decisions is more important, then every detail about what those decisions are individually, or whether we like them, I think what is more important is building that foundation.

That foundation can then be used to explore all kinds of different projects, different syntaxes, semantics, subsets, supersets, ABIs, dialects, DSLs, editors, tooling, etc.

Allowing people to explore different ideas while still being able to build bridges between these different projects with reasonable effort and good tooling.

4 Likes