Hacker News new | past | comments | ask | show | jobs | submit login
Zig in 30 Minutes (gist.github.com)
279 points by dnautics on Jan 3, 2021 | hide | past | favorite | 158 comments



Hey man, first of all thanks a lot for you efforts. This and ziglearn.org are just great as a starting point.

If I may here are three additional pieces of information that if added to your documentation will clarify some more things for the beginner/reader:

1) Arrays and Slices section

Arrays in Zig are values. They store the pointer and the length, but an array is a value so the raw pointer can never be accesses unless....

You coerce the array to a slice. A slice reveals a pointer to you.

2) Add tagged unions (I do not understand what they are but they exist, maybe some fellow reader here could help me)

3) If, for, while and switch can ALSO BE EXPRESSIONS!

Now to the part that does not address you directly but everyone.

These tutorials are great, but they are the mere starting point. I admire Zig and its design, I admire Andrew and that awesome community, I love Zig Showtime and everything. But there are two problems I have with Zig that annoy me and that is only because I REALLY want to learn it and ditch C already:

* I am trying to figure out how to do system's programming. Like use all the system calls and their system library wrapper equivalent's that I am so used to in C. After an hour of research on the net I could not even figure out how to read in and go through the contents of a file (fread, fstat, fgets, fopen). That stuff needs to go into the official documentation or at least to ziglearn.org

* The same way the Zig compiler is awesome the underlying build file you often wanna write is just horribly documented. I don't understand half of it and it changes a lot. Andrew should really politely ask people on the internet to take down old repos and blog entries. Please document the build system and build file writing better.


Maintainer of ziglearn.org here. I have just now added details on using stat and directory creation + walking here:

https://ziglearn.org/chapter-2/#filesystem

And details on reading the next line here:

https://ziglearn.org/chapter-2/#readers-and-writers

fread/fstat/fgets/fopen is now all covered. The build system is something I need to cover much more thoroughly, but is something that will take a long time.


DUDE WHAT. I hope not just because of my post. Anyways that is so amazing thank you so so so much. I post something, you come along and just basically say "wish granted" :D.... You and your page are just great!!!!!! thx!!!


> 2) Add tagged unions (I do not understand what they are but they exist, maybe some fellow reader here could help me)

It is probably a matter of terminology. For some reason different languages see fit to give the same thing different names.

A union is a type that can be one of several different things. In C unions, there is no built-in way to tell which of those things any given union instance is at any given moment, which can lead to code assuming it is one thing when it is actually another. Tagged unions carry an enum with that that tells you which thing they are right now. Zig will not let you work with a tagged union's value unless you switch on the enum (tag) so you know what you're working with.

> * The same way the Zig compiler is awesome the underlying build file you often wanna write is just horribly documented. I don't understand half of it and it changes a lot. Andrew should really politely ask people on the internet to take down old repos and blog entries. Please document the build system and build file writing better.

Agree wholeheartedly. I've never even bothered to use zig build in years of working with zig because of it. Granted, I make it a rule to rethink what I'm doing if I actually need a complicated set of build steps, but sill.


Documentation is definitely not the language's strong point just yet, but that's understandable when it's still on a 0.x release and it's a massive work in progress with ambitious goals. The reference is useful at a high level, the autogenerated stdlib stuff is highly hit and miss and I suppose will be ripe for community contribution when the method of generating it is nailed down.

The language itself is fantastic once you get a decent grasp of it, which you'll probably achieve by reading the stdlib source to get a feel for what you need to do.

I've been using it to build stuff on my Pi Zero. Still hit a few snags with cross compilation and C interop, but it's been a pleasure to write. I'm definitely keeping an eye on it as a good alternative to getting into Rust.


I'm also looking to use Zig for a Pi. Any tips? If you publish a blog post please give me a ping!


I've put it all here if it's any use for ya :) https://www.kamelasa.dev/programming/gettin-ziggy-with-it-pi...


Hey, thanks! That's a brilliant post, awesome tone and a huge help. I really appreciate it and have passed it on to everyone at work.


I'll collect my thoughts on it as I'm still not completely there, but I'll have something when I've got it working.


I remember doing some basic IO using clib. There’s is a flag, like —link-clib or something. Then you can include header files as you would in C. I created a basic example a while ago doing some basic IO, epoll, timers, and linking in a C obj file, just to try out how to do embedded in zig. It’s really good.

Another upside with Zig coming from the embedded world is Zigs idea of doing async/await - since you define the building blocks yourself, it’s really easy to create an async/await-implementation e.g. on top of epoll, but for those times when your hacking on bare metal, you can just write an implementation which fits that particular hardware. It’s really, really good.


Oh damn I should have realised importing C files would be a solution and I will definitely try that. However, I would still much prefer a native Zig way.


Hey overflyer, thank you for the kind words, and the criticism too.

What you're asking is absolutely reasonable and I agree that these are things that should exist. The blocker (for the things that I control / can contribute to) is mostly effort and resulting value.

I considered the idea of working on a book that would do a proper introduction. It's something that would be useful, without a doubt, but the problem is that it would take a lot of effort and time (given my current skillset) and it would take away from other possibilities that in my estimate would be more cost-effective for the project.

So the TLDR is that we're genuinely thinking constantly of what's the next best move to make and, given the situation the project is right now, we think other things have to take priority. Of course we could be making a wrong estimate, so we're open to discussing it, but we have to follow the path of least resistance, which means making temporary compromises.

My bet is that if we play our cards well there will be enough skilled communicators interested in writing Zig programming manuals, we just have to get there first :)

I also want one day to write a book on comptime, hopefully it won't take too long!


Omg is that you Loris? Never ever have I written a post and got that amount of nice feedback. First the maintainer of ziglearn.org and now you.

This is the thing I love so much and if you guys combine this absolutely amazing attitude with some professional marketing I just see a bright, bright future for the Zig language.

I tried all the so called C replacements, and especially Rust. The Zig language is the only approach where one does not need an IQ of a 130 to learn it. Just please you guys do everything to not vanish into a absolute niche like D did, because D was and in my opinion still is such a great candidate/language, they just should have done better marketing.

I would be looking forward for your book and would be the very first one to buy it!!! Also, can I donate to ziglearn, Zig Showtime and/or the Zig Foundation?

In my opinion Linus should think about letting Zig into the kernel and not Rust :D. Maybe one day you guys will also achieve that.


Yo it's a-me, Loris!

Thank you again, we try :)

If you want to support the ZSF, here you can find all the information you need: https://ziglang.org/zsf/ I'm the one answering mails to donations@ziglang.org, btw.

For ziglearn and Zig Showtime, I guess you should check our respective GitHub profiles.


Something like this for build.zig would be amazing, https://ziglang.org/documentation/master/#Zig-Build-System is pretty light on the details based on what I've seen in the wild projects do.


There are some very clever concepts in Zig (I like the fact that types are compile time values), but the language doesn't seem to be as carefully designed as some others. For example, for-loops only work on a few, blessed types.


Consider the domain Zig targets -- low-level programming -- and other languages targeting it: C, C++, Ada and Rust. The first is very simple but severely lacks in both expressive power and safety, and the other three would all easily make any list of the top five most complex programming languages in the history of software; they're byzantine temples for those who worship at the altar of accidental complexity.

Zig offers a radical design. It seeks to be as simple as C — which is particularly important in low-level programming for both portability [1] and humans and machine analysis — while also giving you safety and high expressivity. Obviously, radical design means doing things differently.

Zig rejects any kind of implicitness; all calls must appear as calls. This means no operator overloading, no destructors, and no magical traits. It does so, however, without giving up on expressivity by using other mechanisms.

All low-level programming languages suffer from low abstraction. That comes with the territory. By that I mean that implementation details (especially around memory management) are hard to hide. Changing those details in some component often require changing the clients of that component as well. But C++ and Rust have a design philosophy that tries to hide this intrinsic quality of low-level programming by making the final code appear on the page as if it has abstraction capabilities similar to high-level languages. Of course, that illusion breaks as soon as you try to change code, and it's debatable whether this design helps or harms program comprehension. Zig rejects the C++ philosophy in favour of a brand new, and pretty revolutionary one, that reimagines how low-level programming is done. Unlike Rust, Zig isn't a cleaned-up C++ with a few extra tricks, but it isn't a new C, either. It's something completely different.

You might prefer Zig's design for this domain (as I do) or you might prefer the more traditional C++ design, but the great thing is that Zig is so simple and easy to learn that it's easy to try and find out.

[1]: Consider what it would take to port C++ (or a C++-like language) to new microcontroller you build. You would either need to port LLVM or an extremely complex compiler — a huge undertaking. This is why C (well, there's a tiny bit of Ada, too) still reigns supreme even in domains where correctness is of utmost importance: https://youtu.be/uqan23518Yc?t=632


What would be accidentally complex about Rust? Sure, if you don't provide the static guarantees that Rust does (and only Rust provides AFAIK), you can be a lot simpler :)

The more I use Rust the more I am convinced I can write high level performant code. I mean it's ridiculous that sometimes I forget I am writing Rust and not Scala!!


Rust, like C++ if not more, elevates certain technical details like lifetime, static vs. dynamic dispatch, partial evaluation, and sequential composition ("default" vs. async) to multiple layers of syntactic constructs (types, generics, macros). That focuses the language on accidental complexity, although some people do find that C++ design philosophy appealing (I would expect some high correlation between people who like Scala and people who like Rust as I would between those who don't like either). Of course, it's a matter of personal aesthetics, but I think that style is misapplied for low-level domains, putting a lot of effort into a veneer of high abstraction without actually providing it (you still have to think about these aspects, as you do in all low-level languages, and, much more importantly, it still requires changing client code when details change, as in all low-level languages -- i.e. changing a Rust program is not like changing a Scala program), doing, IMO, more harm than good.

As someone who does a lot of low-level development, before Zig I didn't think any approach other than that of C or that of C++ was even possible. I don't know if Zig will fulfil its promise, but its radical design, that's unlike anything we've ever seen, sure offers a fresh perspective on things.

As to static guarantees -- they are never the point; they are a means to an end: writing more correct programs. That goal is just as valued by Zig as it is by Rust, Zig just tries to achieve it differently. Which achieves it better? It's hard to know right now. I have little doubt that Rust could make things that are today written in C++ safer, but I have serious doubts whether it would be adopted in truly safety-critical domains, where C is king. I think Zig could be.


Thanks for your insights in the matter. I have tried writing a VM with Rust (crafting interpreters) but outside of that I don't have a lot of low level experience with it. I am also in the minority that believes Scala codebases are simpler than all the Java codebases I have come across. Maybe it's just me :D

I didn't know Zig can provide memory safety using it's features. If that's the case it's great, I need to try it out! Although I am sceptical about the claim that in truly safety-critical domains Rust would not be adopted where Zig would, but I am again out of my depth here, so :)


> I didn't know Zig can provide memory safety using it's features.

Yes, although this is done through runtime checks (that can be optionally disabled) rather than through static sound guarantees (Rust uses runtime checks in some cases, too). The language's simplicity and fast compilation helps with other types of correctness, too (i.e. beyond memory safety).

> Although I am sceptical about the claim that in truly safety-critical domains Rust would not be adopted where Zig would

I don't know if Zig would, but Rust has several problems for such domains that C and Zig don't: porting it is a challenge (both Rust itself and LLVM are very complex), understanding what a program does is a challenge (a lot of implicit behaviour), and handling allocation failures is a challenge.


Hopefully during 2021, LLVM won't be any longer the only option to compile Rust, as the work for integrating cranelift backend into stable keeps going on.

Zig also has the same issue with LLVM until the language is fully bootstraped and the original LLVM based compiler no longer part of the build process.

However, packaging a C and C++ compiler alongside for the ride doesn't make it that much simpler.


> LLVM won't be any longer the only option to compile Rust, as the work for integrating cranelift backend into stable keeps going on.

That might not matter. Porting Rust might not be a simple undertaking, either.

> Zig also has the same issue with LLVM until the language is fully bootstraped and the original LLVM based compiler no longer part of the build process.

Yes, but that's expected to happen before 1.0.

> However, packaging a C and C++ compiler alongside for the ride doesn't make it that much simpler.

C isn't an issue at all; C++ is. I'm pretty sure it could be made optional.


I like Rust for the reason you've stated, but it is absolutely both complex and full of potential for implicit behaviour. `Copy`, `Deref`, and `Drop` traits immediately spring to mind, but there are also weirdly specific things like having `no_mangle` and `static` on a global variable when targeting WASM implicitly exports (the address/offset of) the variable for use on the JS side.

Procedural macros are also somewhat insane in many ways.


Try compiling a program with nostd and nocore - try targeting a weird platform, like a small embedded device. You immediately find out how many hidden layers there are to Rust, it’s borderline annoying. Rust is an amazing language, but stuff like mem transmute and I don’t know - it’s been a while now - just trips you up. It’s possible that I just don’t “get” rust, but maybe that’s also the problem. Zig is so easy it’s hard to get wrong. Zig favours readability and understandability over everything else. I can easily grasp complex questions like “will this overflow my very limited call stack” in Zig - it’s harder in Rust (for me anyway).


> It seeks to be as simple as C

It seeks too, but fails. Comparing to really-simple C, it's full of arcane stuff.

> Zig rejects any kind of implicitness; all calls must appear as calls.

We already have that in C.

> Of course, that illusion breaks as soon as you try to change code

That's one of the traits of Zig too it seems. My favorite example of Zig's poor design is following case:

Suppose you have a function call:

    collectNoInline(gc);
And you want to annotate it for being never-inlined (call-site level annotation for "always inline" and "never inline" is a customary enough task in low-level programming). So, in Zig, annotated call transforms too:

    @call(.{ .modifier = .never_inline }, collectNoInline, .{gc});
Ref: https://ziglang.org/documentation/master/#call

I'm sorry, but that's total nonsense. Shows that not enough good faith went into Zig design. Even in C, that could be syntactically annotated as:

    /*pragma:noinline*/
    collectNoInline(gc);


> Comparing to really-simple C, it's full of arcane stuff.

I think it's quite the opposite. Don't forget that C also has macros and a lot of arcane undefined behaviour. I don't know if Zig is as simple as C -- it doesn't have macros but does have, say, slices and comptime -- but it's also much safer and much more expressive. Overall, it's a very simple language, that's very expressive and also quite safe.

> That's one of the traits of Zig too it seems.

Absolutely! It's a feature of all low-level languages. Zig, however, unlike C++ and Rust, doesn't try to waste its complexity budget on making it seem like a high-level language when you just look at the code on the page (and it has other downsides, too, besides language complexity).

> I'm sorry, but that's total nonsense. Shows that not enough good faith went into Zig design. Even in C, that could be syntactically annotated as:

And I'm sorry, too, but I would say it's an example of Zig's exceptionally great design at this stage. If at some point it turns out that adding a new kind of syntax element here is worthwhile, it can always be added later. When in doubt -- leave it out. You never know when your complexity budget is best spent, and if you already have a general means of doing something without a new syntactic category, it's best to wait and see.


> I think it's quite the opposite. Don't forget that C also has macros and a lot of arcane undefined behaviour.

C lexic-based "macros" are implemented by a separate component, "C preprocessor". C clearly needs a AST-based macros, not a whole new language to replace it. Undefined behavior comes from the fact that C is machine-independent assembler (with structured syntax), so to be exactly that ("machine-independent" and "assembler"), it has to underspecify machine-specific matters, like what happens if you shift 32-bit number by 33 bits.

> I don't know if Zig is as simple as C -- it doesn't have macros but does have, say, slices and comptime -- but it's also much safer and much more expressive. Overall, it's a very simple language, that's very expressive and also quite safe.

Those are points which I doubt - it's clearly not expressive enough, and there're safer languages either. Is there niche for it? I'm on a fence with popcorn. But as I look to it, I see things which I consider "mistakes". And I love to talk about mistakes!

> And I'm sorry, too, but I would say it's an example of Zig's exceptionally great design at this stage.

Expectedly, I don't buy this "worse is better" argument either. It's not good when you annotate a simple call and it turns from a simple call into an ugly mess. It's not rocket science to come with a syntax which would avoid that. If Zig language creators didn't do that so far, that's exactly what I call "not enough good faith went into Zig design".

Your appendix of "so far" is accepted - keep up the great work!


> C clearly needs a AST-based macros, not a whole new language to replace it.

But that "whole new language" is probably smaller than just AST macros for C. And C's problems aren't solved just by fixing macros (I think AST macros are a horrible feature in almost any language that isn't a Lisp; I see them as a sign that the language designers just gave up).

> Undefined behavior comes from the fact that C is machine-independent assembler

True, but that's almost never a valuable thing these days; you lose portability and get little in return other than a somewhat smaller compiler.

> it's clearly not expressive enough

It's at least as expressive as any other low-level language. Any C++/Rust program -- with generics, concepts, destructors, async, traits, macros -- could be translated to an equivalent Zig program that's at worst no longer than some (small) constant multiple of the original. That's not true for C (at least not without hurting performance).

> and there're safer languages either

Low-level? Not so sure. The goal is a language that makes it easy to write correct programs, not "a safe language". I'm not sure there are languages that do that better.

> I don't buy this "worse is better" argument either

It's an "it's just better" argument. Good design is not about picking arbitrary things and making them more convenient, but about spending a certain budget in a way that yields a good gestalt.

> It's not rocket science to come with a syntax which would avoid that.

Sure, but you can add that syntax at any time. It's not urgent. It's best to see if you could perhaps generalise it in some way and get a better return, or maybe invest your complexity budget more wisely elsewhere. I doubt compiler directives make up more than 0.1% of a program.

> If Zig language creators didn't do that so far, that's exactly what I call "not enough good faith went into Zig design".

I've been programming for ~30 years, and aside from Scheme -- maybe -- I don't think I've ever encountered a better-designed language than Zig. Of course, this perception is subjective.


I wouldn't call that careless. So far, proposals to extend the for-loop have not passed the cost/benefit test. I think supporting iterators would require something like magic-methods, which so far are not a thing in Zig (language syntax doesn't interact with userland code).

The status quo for iterators is this:

  var it = getSomeIterable();
  while (it.next()) |item| {
      ...
  }
IMO it's "good but not great" (not great because it adds a var and the variable pollutes the outer scope). But the alternative is a bit of a pandora's box.


Honestly, I know it's minor, but when I tried Zig the fact I couldn't do the classic for loop to do a "for (int i = 0; i < n; ++i)" was quite annoying. It pollutes the scope, so you need to add scope braces every time, and I find it's much easier to forget the ++i at the end of the while loop.

I understand where it's coming from, but having something like "for (i32 i in [0,n[)" would be so much nicer in my opinion.


> and I find it's much easier to forget the ++i at the end of the while loop.

You can do:

    var i: usize = 0;
    while (i < 10) : (i += 1) {
        ...
    }
or

    var i: usize = 0;
    while (i < 10) {
        defer i += 1;
        ...
    }
although the two have slightly different semantics (the latter would increment even after a break; the former wouldn't).


Given how Zig does not allow variable shadowing (which is a choice which makes sense on its own) I find the scope leak to be very annoying in practice.


Neither of those fix the scope leak, tho.


This is true. There have been proposals to alter the `while` syntax to fix the scope leak, as well as proposals to extend `for` to support ranges, but none have been accepted (and they aren't very compelling in my opinion).

Honestly, I'm not sure why people think it is such a big deal. I've written a lot of zig, mostly gamedev stuff, and I rarely use that construction. I find that the vast majority of loops are over arrays or slices.


While I don't have much experience with Zig, I agree -- from my little bit of playing around, it also hasn't been a big deal.

(The biggest thing I've hit that I want is a way to return information with an error. If that were fixed, I think Zig's error handling would be perfect.)


Loris Cro did a great talk on error handling in Zig, which also deals with how to return information with an error if you need to, and why the common case optimizes for simpler error values: https://www.youtube.com/watch?v=TOIYyTacInM


Thanks, that was a nice talk.

But the answer there is basically, "if you care about payload, don't use zig's built-in error handling." Which, obviously, you can do, but I'm not convinced it's a great answer!

Even for something as simple as parseInt, it would be nice, I would argue, if it returned, along with InvalidCharacter, which character was invalid. This would enable e.g. very precise indications in messages to the end user of what was wrong with the input.

In general, because currently it's super-ergonomic to return just error codes but more of a pain to return errors w/ payloads, what you'll get in practice is no error payload even when it would be useful, which will end up turning into less-helpful-than-ideal errors for end users, which is contrary to zig's goal of enabling the creation of perfect software. :-)

I found this thread interesting

https://github.com/ziglang/zig/issues/2647


Thanks for the link to that proposal.

Just thinking out loud, given Zig's errors primarily allow the compiler to enforce that errors are handled, and exhaustively, beyond that why can't error payloads just be passed as an input argument pointer to the function call? Maybe this is a dumb idea, but it's what C programs already do, except C programs don't have the safety of compiler checked errors offered by Zig. Does the Zig compiler need to check error payloads beyond the type system already provided? I'm not sure.

I agree with you that having such a super-ergonomic error handling system will direct most code towards a certain style, but I don't think this is contrary to Zig's goals of perfect software or simplicity. It's already such a huge win on top of C's error handling.


> Just thinking out loud, given Zig's errors primarily allow the compiler to enforce that errors are handled, and exhaustively, beyond that why can't error payloads just be passed as an input argument pointer to the function call?

Yeah, that's definitely a reasonable way to do it, and actually Andrew gives an example of this:

https://github.com/ziglang/zig/issues/2647#issuecomment-5898...

(Andrew's example is slightly different in that rather than an explicit argument, it's an optional field in one of the arguments.)

So it's definitely not like crazy bad or anything, but also definitely less ergonomic than if you could directly return a payload with the error, and this is enough friction that it feels like you'll end up not having error information when you want it (both as an API consumer and eventually as an end-user looking at an error message).

But, I'm still very new to Zig, so perhaps my instincts on that are wrong. :-)


> But, I'm still very new to Zig, so perhaps my instincts on that are wrong. :-)

Maybe you're right too! Just speaking for myself here, but as a programmer and "man with a hammer", I sometimes like to think that instincts might just be our mental machine learning model, where it can be really well trained and give the right black box answer, albeit not with the explanatory backstory or rationale, but worth trusting nevertheless.

I'm also new to Zig, and there are ways that a pointer input arg as error payload could go wrong. I'm following the proposal issue, and it will be interesting to see which way it goes.


I think you're spot on with your description of instincts. Which of course means sometimes they can lead us wrong, especially if we're applying them to domains very different from those they were trained on.


To me the scope leak was annoying because how Zig does not allow shadowing, so I have to write:

  var it = a.getSomeIterable();
  while (it.next()) |item| {
      ...
  }

  var it2 = b.getSomeIterable();
  while (it2.next()) |item| {
      ...
  }


You can do:

  {
    var it = a.getSomeIterable();
    while (it.next()) |item| {
        ...
    }
  }
  {
    var it = b.getSomeIterable();
    while (it.next()) |item| {
        ...
    }
  }


Yeah, it's not that common in general, I agree. I think my impression was coloured by the fact I tried Zig to implement a binary protocol deserialiser where getting the size first then iterating happened a lot.


The pattern I use for that is:

  get size
  allocate slice
  for(slice) |*elem| elem.* = read()


Both forms feature "implicit flow of control", contrary to Zig's stated goals. In "while (i < 10) : (i += 1)", it's hard to understand what the heck "(i += 1)". The best concept one might get is that it's puposely made be different from C, just to be different and confuse people.

In second case, it's "defer", coming from Go, the language which chickened out to add normal exceptions, because they're "implicit transfer of control", and LOLishly added "defer", as if it's not such.


> Both forms feature "implicit flow of control", contrary to Zig's stated goals.

They absolutely don't. All control paths are explicitly represented by syntax (no different from the hidden goto in a while loop -- it's explicitly recognised by the while syntax); proof: you can draw all of them by just examining the syntax of the current subroutine, while knowing nothing about others. Exceptions, however, are implicit: any call, foo(), might or might not cause some control flow change in the client without there being any explicit acknowledgement of that by the client; you cannot draw all the flow paths just by examining the syntax of the current subroutine.


Sorry, but throwing an exception in a function call is equivalent to:

    res, exc = fun();
    if (exc) goto exception_handler;
That's underlying model of how exceptions behave, and how they're implemented "manually" in languages with no exception handling (C, Go). You absolutely can draw that by examining syntax of a subroutine, and it's no more implicit than "defer".


Right, both the C style and Zig's defer are explicit, as opposed to exceptions, which are implicit, only Zig's error handling is less error-prone (it forces you to handle errors) and makes the code more readable, IMO, than the C style.


But no, there's a kind of continuum, and Go/Zig "defer" is already pretty high towards "implicit flow of control" end. (I agree that exceptions are a notch higher.)

It's only C's syntax which is truly explicit. It's literally a structured machine-independent assembler. That's why it's gold language which is very hard to displace (it's already perfect for what it is). But just as everyone I'm watching with popcorn all the contenders popping up. (My humble opinion about Zig's issues on that path, I, together with other people, expressed here.)


> is already pretty high towards "implicit flow of control" end

Its implicitness is zero -- there is zero information not available in the syntax of the current block, exactly as in C -- so I don't see how it can be high compared to anything. You just don't have it in C, so you're not used to it. This is exactly like an Assembly programmer who says that C's `while` is implicit because there is no explicit jmp. In fact, the third clause in C's `for` header works almost exactly like defer: you write a piece of code that isn't executed immediately after the preceding one, but is injected to the end of the block.

A language with `while` isn't any more implicit than a language with just goto; it just has another explicit control-flow construct. Same goes for defer.

> It's literally a structured machine-independent assembler.

Not so much once you take the preprocessor into account.

> it's already perfect for what it is

I think that was true in 1970, not today. First, we know more. Second, we write much bigger programs. Third, "structured assembly" isn't as valuable as it was now that even machine code is "high level." This is not to say that C could be replaced everywhere, but I think, intertia aside, it could be replaced almost everywhere.


> Its implicitness is zero -- there is zero information not available in the syntax of the current block

Ah, so your mind's window is single block, that what you bang on. You know, blocks can be long too. To the end of reading 1000-line block, you think that you know how it ends. But oops, you completely forgot about some "defer", which implicitly executes at the end of block. That's my definition of "true explicitness", where all code which executes at some point is available locally.

And if you forgo that definition of explicitness, why stop at block? Exceptions work across blocks, i.e. on the level of the entire subroutine, and not much harder to reason about than "defer".

> In fact, the third clause in C's `for` header works almost exactly like defer

Good point. It's a clause in "for", so best practice is to use it for "loop iteration expression". It's also familiar syntax to the entire generations of programmers. Unlike Zig's "2nd clause in while" which is "original design" people will "thank" you for.

> it could be replaced almost everywhere.

The question is with what. IMHO, Zig isn't good enough to replace C at all. Too much NIH, again. It does too much differently. Naive thinking is of course "so that it's better", but actually, it just repeats C's mistakes (ugliness in language) and makes its own, "very original" ones.


> That's my definition of "true explicitness", where all code which executes at some point is available locally.

But no control flow construct satisfies that. Jumps are the whole point, and the unit for structured control flow is the block (what's the next instruction after `break`, `continue` or `}`?). defer is just as structured, just as local, and just as explicit as C's control flow constructs.

> It's also familiar syntax to the entire generations of programmers.

True, but learning Zig takes a day; two tops. Where it differs in syntax from C, it does so for good reason, and it's not like it's a complex language where different syntax is an additional burden. C's `for` syntax just doesn't make sense (`;`, which everywhere else in the language denotes sequential composition, means something different in the `for` header). Is an additional 2 minutes of learning, in a language that has very little syntax, not worth fixing something that's unpleasant in C?


> while (it.next()) |item| {

Talk about confusing, implicit syntax of Zig - there's no connection between "it.next()" and "|item|". It's implicit and you need to make it up. Compare that to other languages: "for item in it" or "while (item = it.next())".


It isn't confusing. The meaning of the syntax isn't obvious if you didn't bother to learn zig syntax, but it is entirely consistent with how zig does this sort of thing.

The for loop payload syntax, where you can also give a name to the counter, is the only weirdness with it.


I'm sorry, but I do programming languages for decades, and familiar with a bunch of them. There's absolutely nothing special about Zig, it's yet another wannabe proglingo. What sets it apart is strong desire "to replace C" while being apparently "as different as possible from it".

I understand such a strategy (among many possible), and that will be a fun strategy if it pans out. The current situation though is that people question: why that dude purposely make it harder than needed for everyone?


> There's absolutely nothing special about Zig

That's just not true. It is not only pretty exceptional in its general partial evaluation construct combined with compile-time introspection (although D and Nim have some similar features), it is the only language AFAIK where a single general partial evaluation construct is used in stead of type generics, value generics, typeclasses/concepts, constexprs, macros and conditional compilation.

Zig might not be your cup of tea, and that's fine, but it is without a doubt unique in its design and not only special, but pretty radical.

> Talk about confusing, implicit syntax of Zig

I don't think it's any more confusing than any other syntax (and less confusing than C's `for` syntax where the ubiquitous `;` is treated differently than anywhere else), even though it might not be familiar to you before learning it, but there is absolutely nothing implicit here. You might find `in` more appealing to you or more familiar than `|` but it's certainly not more explicit.


I feel like what you're complaining about is the equivelent of Calculon's critique of a screenplay: "no, I don't like the font". I am very much not a genius (check the user name) and it took me less than a minute to understand the payload operator (which IIRC was taken from Ruby or something).

Let's say `for (x in y) {}` replaced the payload operator. It would still exist in:

- if(some_error_union) |value| {} else |err| {}

- if(some_nullable) |value| {}

- while(some_nullable) |value| {}

- switch(some_tagged_union) { .some_tag => |value| {} }

And any that I might be forgetting. Is your suggestion that each of these should have separate syntax, thus complicating the language with one-off syntax?


> I feel like what you're complaining about is the equivelent of Calculon's critique of a screenplay: "no, I don't like the font".

Syntax is not irrelevant to the main use of a programming language the way fonts are to the use someone is probably concerned with if they ask an opinion of a screenplay, so, no, I don't see a similarity there.

> it took me less than a minute to understand the payload operator (which IIRC was taken from Ruby or something).

Loosely inspired by Ruby, perhaps, but definitely not taken from. Neither the positioning nor the semantics are the same.


> I feel like what you're complaining about is the equivelent of Calculon's critique of a screenplay: "no, I don't like the font"

I'm a human, and syntax is very important to me. 't broken read can syntax I. In that regard, if you purposely (or naively) misuse Comic Sans, then yes, "I don't like the font".

> (which IIRC was taken from Ruby or something).

Bingo. Ruby's not everyone's favorite language, so please be ready that people will send you rays of some hard love in that regard. Did you consider using C syntax for C-replacement-wannabe? (Rhetoric question.)


From what you're saying, I believe you would complain about a foreign language simply because it doesn't resemble your native language enough. Zig's syntax choices are not arbitrary and great effort is made to ensure their consistency. Your complaints about the syntax aren't that there is anything inconsistent or illogical about the syntax, just that it isn't the syntax you're used to.

That's a valid reason to not want to use the language, but I don't believe it is a valid basis for criticism and certainly doesn't excuse the hostility of your comments in this thread.


> From what you're saying, I believe you would complain about a foreign language simply because it doesn't resemble your native language enough.

I assume you mean a natural language. No, I won't complain about a real language used by people. I might criticize someone's inventing their own natural language. The same as I do for programming languages. And I'm very well familiar with the "we need to invent to move forward" argument. I also assume that people taking that ungrateful task are aware that they will receive criticism for that.

> just that it isn't the syntax you're used to.

Not just me, but many people. I specifically started to comment, seeing other people's feedback resonates with my own sentiment about Zig.

> certainly doesn't excuse the hostility of your comments in this thread.

I don't think there was particular "hostility", but I indeed try to nail right at the spot of the issues. Ouch! Beyond that, I allowed me some sour comments regarding downvoting other peoples' and my comments where concerns were raised with way Zig does some things. Such downvoting could be considered hostility, but I actually consider it funny ;-).


If you go into a conlang discussion and complain about people inventing languages when there's already natural languages, I guarantee you will get downvoted and pretty much for the same reason.

Let's look at some of your criticisms:

  > @call(.{ .modifier = .never_inline }, collectNoInline, .{gc});
> I'm sorry, but that's total nonsense. Shows that not enough good faith went into Zig design. Even in C, that could be syntactically annotated as:

  > /*pragma:noinline*/
  > collectNoInline(gc);
In which you say that a built-in function call with optional flags and settings is total nonsense, while hijacking comment syntax to change compiler behavior is better. You can make an argument for that, but the way you describe it as "total nonsense" and not in good faith is definitely hostile.

Let's look at some more examples:

> Jumping thru hoops is what Zig seems to choose with its unorthodox, different-just-to-be-different syntax.

> Zig appears to have strong NIH mentality in regard to the syntax. Trying to replace C, but go out of their way trying to invent syntax just to be different from it and most other things too.

Zig's syntax isn't that unorthodox except compared to languages that look even more like C than it does, and it definitely isn't different just to be different. By claiming such, when there are thousands of posts in discussions about syntax, is plain insulting. Can you provide even a single post that suggests anyone has ever suggested syntax be a certain way just to be different?


https://www.nmichaels.org/zig/interfaces.html

There is an example here for a kind of iterator.


Nice work. It would be great if you could add a Zig page on https://learnxinyminutes.com.



> std.debug.print("foo param: {}\n", .{x});

Why is this ".{x}" and not just "x"?

This syntax is used tens of times in the following code snippets but never explained.


Thanks for the catch! It's an anonymous array. Later down there is a place where there are two sets of brackets in the print string, and the so the anonymous array passed to it has to have two items (the string is analyzed and the correct size of the array is compile-time checked, no stack drilling here).


Does this mean that "print" only takes two arguments, and the second argument has to be an array?

This is the kind of information that your tutorial needs to contain, because it's radically different from C and other languages, and this is exactly the kind of information that readers will be looking for: "How different is Zig from C and why should I care?".


Yep! The document has now been updated. I might have been blind to it because my daily driver is Elixir, and it does "basically the same thing" with keyword arguments.


I totally understand why being immersed in something might make you lose perspective, but keeping this perspective is what differentiates a decent language designer from a great one.

Does this mean that zig doesn't support varargs? If not, why not?

Again, another question that a lot of people coming to your page will be asking themselves, please don't take that as a criticism, just candid feedback to help you make your article better.


Zig does not have varargs. They were removed in favor of anonymous structs/tuples. See https://github.com/ziglang/zig/issues/208#issuecomment-39377....


I'm not the creator of zig! Thank you for your advice.

Zig does not support varargs, except when calling C functions.


Isn't it an anonymous struct, not an anonymous array? (IIRC it can't be an array, since it must support heterogenous types)


You're right! It's an anonymous struct with numbered fields. I forgot about that.


To allow for multiple substitutions to be done the same way.


Sorry but that doesn't explain anything.

Why is just "x" not allowed? What does ".{x}" actually mean?


.{ x } or .{ x, y, z } etc... are adhoc-constructed anonymous struct-values which can be inspected at compile time by the standard library's string formatting code.

It all makes a lot more sense after understanding Zig's comptime features:

https://ziglang.org/documentation/master/#comptime

The end of the comptime section also explains how string formatting works that way.


I am always interested in zig, but these mini tutorials don't give you anything beyond what simple C does (apart from the exceptions). The full docs do not have enough examples (last time I checked). I would really like something like K&R for zig.


Hi, I am currently writing ziglearn.org which aims to show a lot of detailed examples.


Please include the following if you have a chance:

- parsing command line arguments

- logging (loglevels, files, stdout/stderr, etc.)

- talking to a restful service via HTTP

Thanks in advance!


Getting command line arguments is covered here:

https://ziglearn.org/chapter-2/#iterators

I don't think that going further into parsing is in scope. std.log is something that definitely needs to be covered. HTTP, I'm not sure about as it requires a lot of extra machinery outside of the standard library and these things aren't mature yet.


It's hard to rationalise putting together a fully fledged guidebook when the lang is still quite unstable, with things changing very regularly. Once it hits 1.0, or possibly a short time beforehand, more people will be willing to both learn the language and/or create in-depth write-ups.


Does this mean zig is not ready for production?


I would recommend avoiding any language in production environments until they at least hit version 1.0, unless you're able and willing to contribute by dealing with issues you encounter as you go, and fixing backward compatibility breakages as the language is updated.


IMHO the official documentation:

https://ziglang.org/documentation/master/

And the (fairly new, and still a bit thin) std library documentation

https://ziglang.org/documentation/master/std/#std

...gives a good enough rundown to start writing real-world code if you're coming from another C-like programming language.


I've also found the std library code to be very clean and readable. Try taking a look at e.g. <zig>/lib/std/array_list.zig


In my opinion it doesn't. I Shows all the features/keywords but it doesn't teach you how to use it properly. I presume you didn't study K&R?


To be fair, K&R (as awesome as it is) also doesn't cover things like epoll or io_uring? And then again, K&R's definitely not a half hour read.

Zig's std lib documentation will keep getting better. In the meantime, the std lib code itself is so well written, it's worth a read, even coming from another language, and even if you have no intention to learn Zig. I found it easy to read and was impressed by the code structure and quality of the design.

Of course, that's not to suggest that code is documentation, but I've learned alot about improving my programming in general, just by reading Zig's std lib.


I do not want epoll and io_urig covered in the teaching material. I mean you don't learn a language by reading a dictionary is all I am trying to say.


> you don't learn a language by reading a dictionary

I love this quote, adding it to my quote list; is it from something?


Glad you like it. I think I just made it up when typing the reply, since the documentation reminded me of a dictionary. But I wouldn't be surprised if this has been said before.


epoll and io_uring (the latter of which did not exist when K&R was written) have nothing to do with C though


K&R C also doesn't teach how to write code that is actually correct in modern C compilers, nor does it teach C best practices on how to at least try to write safe code in C.


Agree. But it did all this at the time it was published. That's just what I would need for zig. It is OK that this doesn't exist, it just mean one person less picking up the language.


Yes, that's the point I want to make.

Zig the language, and Zig the std lib have two different sets of documentation. The former is really, really good, and I wouldn't say lacking at all, considering Zig is still pre-1.0. Take a look here: https://ziglang.org/documentation/master/

It's the Zig std lib auto-generated documentation (i.e. I/O things like epoll and io_uring and much more) that is incomplete, and to which most of the "documentation is lacking" and "read the std lib source" comments relate.

It's only if you want to know how to use Zig for things like I/O, then you'll need to read the std lib source (and the growing number of blog posts and talks etc), in the same way that K&R is also not always helpful as a guide for these things (and others) today in C.

But the Zig language itself is pretty easy to grok from the excellent language documentation and examples already linked to.


For me it is not easy to grok. Then let me ask you: I need a (large) 3 dimensional array where the size of each dimension is unknown at compile time. What is the zig way to do this, how do I access the elements.

Bonus question: I have a function doing a transformation on this array, what is the way to duplicate this array


I've read K&R Second Edition, but only after I already learned C through other means. From that PoV, K&R is an interesting look into the design rationale of C against its historic background, but since it is stuck at C89 I wouldn't recommend it today to learn the language TBH :)


> You can explicitly choose to leave it undefined if it will get set later, but zig will error if you try to use it.

That doesn't seem to be true. The example below this sentence errors because the function foo being used doesn't exist, not because the variable is undefined. A proper example [1] shows that Zig will happily use uninitialized memory here:

    x: -1431655766
[1]: https://godbolt.org/z/36j4ab


Yes, you're right. From the manual:

> [Once a variable is set to undefined], it is no longer possible to detect that the value is undefined. undefined means the value could be anything, even something that is nonsense according to the type. Translated into English, undefined means "Not a meaningful value. Using this value would be a bug. The value will be unused, or overwritten before being used."

> In Debug mode, Zig writes 0xaa bytes to undefined memory. This is to catch bugs early, and to help detect use of undefined memory in a debugger.

https://ziglang.org/documentation/master/#undefined


This is very nice! I think it would be more useful if it talked about the memory model, heap allocations and pointers which I'm guessing is pretty important for anything non trivial.


that's fair! I also didn't go into async/stuff. I'll put a note at the bottom.


Nice work! Can this be also on learnxinyminutes.com (https://github.com/adambard/learnxinyminutes-docs) ?



How do you do modules in zig? Like when you have your code in 5 C files and link the obj? How to do that?


@import can take a path. I guess i should put that in there. The details are pretty cool, the imported file becomes a struct!


So are they all recompiled? What about compilation/linking time? Or is this not a concern since the zig compiler is fast?


Zig sources go into a single big compilation unit. C sources can be split into multiple CUs and Zig has a neat caching system that integrates with clang to only rebuild a CU when necessary (you don't have to do anything to set it up).

An incremental compilation feature is coming to the self-hosted compiler: https://kristoff.it/blog/zig-new-relationship-llvm/


C source files are only compiled on full rebuilds, or when the C source file changes, just like in regular C projects. You can distribute precompiled libraries, but I think given that one of Zigs prominent features is simple cross-compilation to all sorts of platforms, compiling from source is preferred.

The @import method is only for "importing" C headers with declarations and have them automatically converted to Zig interface declarations (so in most cases you don't need manually maintained language bindings). For compiling the associated C soure files, Zig has a builtin C compiler.


I think you misunderstood my question. I am not (in this question) interested in C or C interopability of zig, but how to structure larger zig project (how zig thinks this should be handled)


Yeah, I realized that after I hit send :)

For regular Zig source files, you just import them into other Zig source files, up to the "main file". Such imports are wrapped into a module struct (imported modules are just regular structs). The Zig build system takes care of efficiently compiling all this with proper incremental build support (one can explore the zig-cache subdirectory which is maintained by the zig compiler for details).

For example, these are the imports in a top-level file:

https://github.com/floooh/pacman.zig/blob/ed42fad79c3e9b4432...

The sokol.zig file groups other modules under a common namespace:

https://github.com/floooh/pacman.zig/blob/main/src/sokol/sok...

...which in turn imports "leaf modules" like this:

https://github.com/floooh/pacman.zig/blob/main/src/sokol/aud...

...it's one of the most straightforward module systems I've seen yet in any language.


Just like JavaScript modules, kind of.


Interesting. Some unusual syntax in there, with for loops and arrays, for example. What are some more serious projects made with Zig?


I wrote a shader preview GUI using Zig, Neovim, and WebGPU (basically a desktop Shadertoy).

It's named "Futureproof": https://www.mattkeeter.com/projects/futureproof/


TigerBeetle (an accounting database for a high throughput payments switch): https://github.com/coilhq/tigerbeetle

We're serious in the sense of very much alpha, and with a long way to go, hopefully intersecting with Zig's stability program in the next year or so, but we have some demos and benchmarks in there of using Zig for io_uring. Zig's std lib already has io_uring helpers based on liburing's design, which we contributed.

We would have gone with C for its ABI, OOM-safety and control over memory layout, but considered Zig ready enough given our own medium term timeline, and the developer velocity and safety is already paying off. We also wanted a fantastic compiler, which Zig already provides. I personally wouldn't go back to C for a new project like this.


Not "serious" at all but I wrote a Pacman clone over the holidays as an excercise and test for my cross-platform C header bindings:

https://github.com/floooh/pacman.zig

...and before that I did the same in C99 (might be useful for comparing the languages):

https://github.com/floooh/pacman.c

Disclaimer: I'm not a Zig expert at all, and the project doesn't really require most Zig features that differ from C. But I think writing small and "for-fun" projects like this is important for getting used to a language. I think one of Zig's big qualities is that it is so straightforward, after a few hundred lines you hardly have to look up things in the language documentation anymore.


Thanks! I was using "serious" very loosely, more in a sense of wanting to see the language in action beyond demonstrations and examples.


I saw something similar for both Nim and Rust the other day, both of which I believe target the same space (safer alternative to C).

Anyone who has dug into these care to comment about the pros and cons of each?


Zig: a language that most people who like C but not C++ will probably love. simple and compiles fast and deals with undefined behavior and null more safely than C, easy c interop, no garbage collection

rust: more like a safe c++, you can get all the performance of c or c++ with the memory safety of a garbage collected language, as well as data race safety and nulls do bot exist. downsides are it can be a hard to learn paradigm to satisfy the compile time memory checks, and it is slower to compile

nim: sort of like a statically typed python. fun syntax and features, compiles to C, quickly. has in the past used garbage collection but a new reference counting mechanism has been introduced lately.


Thanks, that's just the kind of comparison I was looking for.

If anyone has an idea about the (A) relative stability of the languages, and (B) the number of libraries/packages for things you don't want to write yourself, that'd be great.

Note:

> has in the past used garbage collection but a new reference counting mechanism has been introduced lately.

Reference counting is a kind of garbage collection. It's often faster than the "hello world" of gc, namely mark and sweep, but it has its own challenges.


Nim is also as programmable as Lisp, and memory safe with automatic reference counting.


Thanks for summing it up, so now I know who Zig is targeted at, and it's not me. 8)


This is a great in-depth comparison of Zig and Rust from the POV of someone who has used both extensively for non-toy projects. https://scattered-thoughts.net/writing/assorted-thoughts-on-...


Wow, this is a really in-depth article, and really informative - thanks for sharing!


Does anyone use Zig for production?


I don't think Zig is production-ready, if someone is using it there must be a special case where they think it makes sense.

Anyway, I don't think production readiness of a language that hasn't reached 1.0 really matters.


That's just a number, each project has their own criteria. Elm is very stable, production ready for more than 4 years and still 0.19


Every project has it's own versioning system, Zig follows semver I think. See https://semver.org/


Jens Goldberg did a fantastic talk on Zig in Production:

https://www.youtube.com/watch?v=124wdTckHNY


Languages, much like startups, are usually successful by focusing in one area and growing that first. The "$LANG in 30 minutes" format seems to play more to a general audience, which I fear will lead to a whole lot of people saying that it looks neat, and maybe they will get to it later.

It might be better to publish a lot of stuff about a single topic, where it can attract interested groups and build enough that it actually proves the merits of the language.


If I understand it correctly, the intent of this format is to let the reader pick up enough of the language to be able to read code without getting frustrated. I think this is a good goal, and there is indeed some value in it. These languages are complex enough that articles in this vein are useful. They are not, and -cannot- should not, replace documentation and tutorials.

Edit: punctuation


is there something like this for scala?


why do you pass an empty struct

```

    std.debug.print("hello world!\n", .{});
```

that kind of extra typing is what turn me off to be very honest, other than that, zig seems like C and Swift had a baby, pretty nice

another thing:

```

const LikeAnObject = struct{

    value: i32,

    fn print(self: *LikeAnObject) void {
        std.debug.print("value: {}\n", .{self.value});
    }
};

```

Why don't make the self: *LikeAnObject implicit?

Again, this focus on extra typing only just add noise in my opinion, function is already wrapped inside the struct, i feel like it HAS to be implicit

-- EDIT --

One last thing:

```

    for (array) | value | {

        std.debug.print("array {}\n", .{value});

    }
```

Not a fan of the | | syntax, it doesn't feel natural

```

    for (value in array)
```

Here it is pretty clear what it does

-- EDIT 2 --

```

const std = @import("std");

std.debug.print("hello\n", .{});

```

is import the right word here? feels like it should be ``use`` since you'll use them this way: ``std.debug.print``

``import`` would be to make all the types directly visible and use this way: ``debug.print``


That not an empty struct, rather an empty anonymous array. It's there because zig doesn't have overloaded function params. Print must take two arguments.

The || syntax is used elsewhere in zig, if statements, catch, switch, etc.

There's no requirement for a function inside a struct to act on the contents of structs, so it's reasonable to use structs as namespaces. This is what is happening when you @import, for example. The imported file becomes a struct.

This is quite different from a lot of other PLs, but it is pleasantly consistent when you get used to it.

There is a usingnamespace keyword to make a structs public contents spill out into the current scope. It's to be used sparingly.

Edit: I'm wrong! It's an anonymous struct with number fields, not an anonymous array.


so it's not a type safe language if they use anonymous struct everywhere

also why ask for a parameter when it is not needed? print vs printf in C


Anonymous struct/tuple/array is a convenience feature that can only be used for values.

Consider the above code without it:

  std.debug.print("hello world!\n", struct{}{});
Now add a value:

  std.debug.print("{}!\n", struct{string: []const u8}{ .string = "hello world"});
Quite unwieldy. Zig used to have variadic functions and it was difficult to work with, complicated metaprogramming, and made how things work less obvious during reading. It was also pretty much only ever used for the "print" function.


> so it's not a type safe language if they use anonymous struct everywhere

It's compile-time checked. The example shows a compile time error when the struct fields are not completed by the anonymous struct


printf in C makes use of variadic arguments (man 3 stdarg) which Zig does not allow (unless you are using a C function) for safety reasons.


Well, on the upside on the ‘for’ syntax, it allows you to say “for (objects) draw” instead of “for (object in objects) { draw(object); }”. So it’s not all bad.

Edit: also, the print stuff, I feel that’s in line with the Zig Zen - make the language simple to understand. Now the print function has a very clear type. Otherwise you need a “smart” print function (like Rust does with a macro or C does with varargs). Easier to understand, not easier to type.


[flagged]


You're probably being downvoted because, while your first two questions are reasonable, your two edits are just low-effort low-value syntactical nitpicking.


[flagged]


hm, somehow you immediately before this one have 2 comments where you criticize Zig that are not downvoted in your comment history?


Oh, so you really expect every comment not singing hymns to Zig to be downvoted? ;-) Well, they now are.


I wish all language as same syntax, no matter whats its implementation, no matter it has cool feature or not. So new comer will get use to it faster.

Why its not int64, int32, unsigned_int32, vec, function for all language, but inventors have to change these to u64, i64, fn...etc?


> So new comer will get use to it faster.

Languages have many competing goals. It shouldn't take long to get used to u64 over, e.g., unsigned_int64, and brevity is valuable in its own right. Too many wasted characters can obscure the flow of a program and make it slower to read and understand.

Is it the right choice? I could be persuaded either way. I know it's one I've personally made before, choosing rebindings like i256 and cmpeq8 when doing a lot of bit-twiddly vector code.


What makes "int" better than "i" as an abbreviation for "integer"? How will you get everyone to agree with you?


I realize I'm stating the obvious, but 'i' is shorter while 'int' is slightly clearer. So I think there's a valid argument for both, but personally I think clarity is more important.

Having said that, less typing and clutter are also beneficial, so it's really a net natural debate.


Clarity is important but I don't see how it suffers from that except for people reading code in that language for the first time. To my knowledge the languages shortening this to one letter are also the kind where the programmer can be expected to already know the fundamental data types, otherwise this syntax won't be the biggest problem.

Personally I prefer it, mostly for subjective reasons but I think it makes sense - in the case of Rust it was the easiest syntactic novelty to get used to, things like lifetime annotations are a different beast.


It existed before. Golang, Haskell, C, D (both kind of - int32_t), caml, and many others. It's i32 that deserves a "why this one?" comment.


C is not a language to emulate unless you think "unsigned short" and "long double" are beautiful ways to express signedness and the number of bits.


That's a weird strawman. The long names are irrelevant here. It's not about C types overall, just stdint. Each of the languages mentioned uses intN in some form.

When people do something differently than most other popular implementation it's good to ask if that's worth it.


> It existed before. Golang, Haskell, C, D (both kind of - int32_t), caml, and many others. It's i32 that deserves a "why this one?" comment.

"i32" and "u32" are used because they are short (and used often). They are just typedef away in C and are used ~forever, did you look at Linux kernel for example?

But I'm with you on the general sentiment - beyond trivial, lexical things like type names (which almost any language allows you to redefine anyway), Zig appears to have strong NIH mentality in regard to the syntax. Trying to replace C, but go out of their way trying to invent syntax just to be different from it and most other things too.

And a lot of people appear to notice and pay attention to this, as the discussion here shows.


Syntax has a heavy influence on function, so if all languages had very similar syntax, they couldn't be ideologically diverse without jumping through ridiculous hoops.


> couldn't be ideologically diverse without jumping through ridiculous hoops.

Jumping thru hoops is what Zig seems to choose with its unorthodox, different-just-to-be-different syntax. I wonder, how many will want to jump with it?


> Jumping thru hoops is what Zig seems to choose with its unorthodox, different-just-to-be-different syntax.

Did zig run over your dog or something? You seem to be particularly hostile in your comments about it. As someone who has participated in discussions about zig syntax for years, I can assure you that a significant amount of thought and consideration goes into these choices. It is not "different-just-to-be-different". In fact, the very syntax being complained about is derived from other languages!


No, I'm adept of (anti)survivorship bias. In other words, I like to study mistakes. And Zig offers a great field of study in that regard, as many issues are seen with a naked eye (i.e. even to casual passers-by).


What syntax would be the default?


Lisp.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: