The website has been refreshed. The feature highlights section on the front page gives many examples of the features with code samples.
Even as someone who follows zig closely (from a distance), I was glad to read that front page again to day to refresh my memory about:
* Cross-compiling is a first-class use case
* Zig Build system
Also, IMO Zig has some of the most exciting WASM related stuff going on in my limited experience as an outsider (to WASM). Following Zig's development of WASM capabilities has taught me more things with less confusion.
> Robust - behavior is correct even for edge cases such as out of memory.
> Optimal - write programs the best way they can behave and perform.
> Maintainable - precisely communicate intent to the compiler and other programmers. The language imposes a low overhead to reading code and is resilient to changing requirements and environments.
Thanks. Based on that definition of optimal, it sounds like Zig intends to be optimally predictable and performant. Other languages would define "optimality" differently: Python aims to optimize readability, Lisp aims to optimize expressiveness, Erlang aims to optimize availability, and so on. I don't mean to nitpick, but choosing an excessively general term as one of the three primary goals seems like a missed opportunity to focus the Zig language community on specific goals.
I've been supporting this project on Patreon for $30/month for 10(?) months now and it is remarkable how much progress has been made. Replacing C would be quite a revolution, but I hope it happens.
I am amazed how much money and effort goes into building software on top of the ancient wasp nest that is C. People boldly taking on that issue deserve our support.
I really, really hope every time they are preparing to push a release, the process involves someone saying "RELEASE ZIG" and someone else voicing their approval by saying "FOR GREAT JUSTICE".
It's [planned](https://github.com/ziglang/zig/issues/615). The feature will only be present in the self-hosted compiler, not the "stage1" C++ compiler, which is what is currently shipped.
It'll be especially well suited for this kind of thing because the self-hosted compiler is a long running process that watches files for changes and rebuilds incrementally. [1 minute demo of early progress](https://www.youtube.com/watch?v=b_Pm29crq6Q).
Just so you know HN doesn't support reddit markup for links, you can only post the url for the link directly, not highlight text. That's why most ppl here use a footnote index to post links [0][1][2]etc
It's not "reddit markup", it's just Markdown. A rather common format, not specific to Reddit. And honestly, I wish HN would grow a few features in this area — links and blockquote would be really nice. It'd be good to have common formatting s.t. common formatting can just get out of the way, so that we can all focus on the discussion, instead of parsing text with our eyeballs.
(FWIW, M↓ is supposed to be lightweight enough that it's readable inline. The links can get a little long, but I think it's not too hard to skip, and it does have the upshot of not making you have to match up citation numbers. But you're right that the numbered format is more common among posters.)
When the raspberry pi 3 hardware boots, it jumps to 0x0. So this is the part where the bootloader loads the new kernel image into memory... starting at address 0!
Zig's type system tries to be aware of what its pointing to. Is it an array of comptime known length? An array of unknown length? An array of runtime known length? or a single item? Is it mutable? What's its alignment requirement? etc. It even has a pointer type for "something that came from C, who the hell knows". There is an accepted proposal to have pointer types for null-terminated blocks of memory too.
So when you create a pointer out of thin air, you have to inform the type system precisely what kind of pointer it is. That's why it is so much more gnarly than C, it wants you to be explicit.
In a system with virtual memory, you would typically ensure that address 0 (i.e. the lowest page) is unmapped. This causes an error condition if the address is ever read or written, which is useful because 0 is used as a placeholder value (i.e. NULL) in many situations. But this is a conscious decision by the system not to use this page, there's nothing technically stopping you from mapping it and putting some data at virtual address 0.
In a bare-metal environment, there's nothing saying that physical address zero must be unused by the hardware designer.
So I think it's quite the opposite: There's no requirement that address 0 must be unoccupied in any situation, it just so happens that many operating systems choose to leave it unmapped as a debugging aid for developers.
In all seriousness, what questions does it raise? HN has a long history of featuring old and new languages on the front page and often you'll bump into language designers and researchers.
I could be wrong, but I recall the front page featuring more esoteric languages/ideas in its early days. (My username doesn't reflect how long I've been here BTW)
didn't mean to ruffle any feathers, it seems like the ones that have appeared lately are "new language like language X but does Y". Maybe I'm getting old and grumpy but can't help but think the time would be better spent adding feature Y to language X, but didn't mean to start anything :-).
You didn't ruffle my feathers, but I can easily see how you'd ruffle the feathers of someone who's invested a tremendous amount of time into a new language.
> but can't help but think the time would be better spent adding feature Y to language X, but didn't mean to start anything :-)
When people create new languages, the premise is rarely along the lines of: "I like this language, but if it only had this feature." The truth is there are a whole slew of very legitimate reasons for creating a new language. Many of those reasons are predicated on the idea that the mainstream alternatives have too many wrong features and/or it would be difficult-impossible to fix those flaws by adding new features. As you already know, it's a lot harder to remove a feature from a mainstream language than it is to introduce a new feature, so languages tend to become more complicated as time goes on. New languages tend to provide a clean slate and opportunity to learn from the mistakes of its predecessors.
Another reason to create new languages: New languages often act as the test bed for ideas that eventually end up in mainstream languages. As mainstream languages mature, they rely on more experimental languages to introduce ideas so they can be tested. The only way to test these ideas is to have people write programs in these languages and study the outcome. With that being said, if it wasn't for the experimental languages, mainstream languages would not likely have things like objects, or lambda functions, continuations, type inferencing, polymorphic type systems, etc.
So, if you find yourself being down-voted for asking questions like, "why don't you just add feature Y to language X", it's because you're in the wrong venue. You're not the first to ask the question. I'm not the first to answer it, so you're bound to ruffle feathers.
Glad to see you still going strong! I’ve been a supporter on Patreon since your job-quitting announcement 10 months ago. How has it been working full time on Zig? Did you end up relocating from NYC?
I'm happier than ever before. When I had a day job, I worked on Zig nights & weekends, and I was pretty stressed out.
Now, I work on Zig during the day and I'm training with my brother for our first marathon on nights & weekends. I'm really thankful for you and others' support so that I can do this.
Still in NYC for 1 more year, but my girlfriend is finishing up her master's and looking for Ph.D. programs in California.
Interesting language. I do find the statements a bit ‘absolute’, eg higher performance than C. In terms of what? Floating point, concurrent processing, ...?
In their phylosophy C and zig both aim to do very little behind the scenes beyond what you explicitly express in your code.
On a technical level Zig re-uses fancy C compiler infrastructure in the form of LLVM.
So that gets them pretty close.
The advantage tha zig has over C is that it gets designed decades later when we have learned so much about what is good or bad or fast or slow about C.
The same could be said for Go. And it still doesn’t explain the statement on performance. I see nothing close to objective benchmarks. I think the language is interesting though and hope this will be published.
C's simplicity leads to fewer guarantees, this makes some optimizations impossible. E.g. Fortran used to be faster than C in numerical code, because the guarantee of no aliasing allows for more aggressive optimizations.
Parameters can have `noalias` on them. This is [currently undocumented](https://github.com/ziglang/zig/issues/1521) and [not yet safety checked](https://github.com/ziglang/zig/issues/476) and there is an [open area of research considering doing it the opposite way](https://github.com/ziglang/zig/issues/1108). Provided that it could be safety-checked, opt-in aliasing has the potential to make Zig even faster. As far as I'm aware, this is currently the only way in which Rust could potentially outperform Zig (and C).
> C's simplicity leads to fewer guarantees, this makes some optimizations impossible.
I know that's the theory, but with few exceptions this doesn't seem to have panned out in reality anywhere and C is usually still the gold standard when it come to performance. How many more decades until we get these sufficiently smart compilers?
The section about overflow put me off. Undefined semantics is one of my least favourite parts of C. It seems from the article that Zig is leaving not only signed overflow but also unsigned overflow as undefined (or runtime crash in "safe" mode, which is equally as bad). In C at least unsigned arithmetic is well-defined so I could get away with some casting back and forth.
This irks me especially badly since the underlying hardware operations are almost always well-defined, but in my "high-level" language I constantly have to worry that I missed something and maybe the compiler will "optimise" my + into something other than addition.
Is there a fully well-defined addition operator in Zig? What about a well-defined shift operator? This might make me, as a professional C programmer, more interested in a new C-like language.
I google'd this - GCC comes close. There are built-ins for overflow-checking add/sub/mul arithmetic. [0] There are also compiler flags to enable explode-on-overflow or wrap-on-overflow, except for division and remainder. [1]
Indeed. What I would really like is a way to toggle it on case-by-case basis. With -fwrapv you have to convince the code owner to toggle it globally, which can complicate things unless you are the owner.
Looks like GCC doesn't have a pragma to enable it on a per-object-file basis. Pity. From the pragma docs I get the impression it's not so much that it would be a bad idea, as simply not something they've got round to implementing.
I don't imagine it's possible to check using a static assert, either.
Would you feel better if it was called "illegal behavior"? In the safe build modes of Zig, integer arithmetic, shifting, wrong union field access, etc is 100% well-defined. Integer overflow is defined to panic. Unless of course you use one of the wrapping arithmetic operators; in these cases it is defined to do wrapping arithmetic.
Integer overflow is usually a bug. If it weren't illegal behavior, zig wouldn't be able to help you catch the bug. That's why clang's integer arithmetic sanitizer only works for signed ints. It's much better for programmers to specify their intent precisely, which is why Zig has different operators for wraparound and assert-it-doesnt-overflow.
Undefined behavior in the unsafe modes is what lets the optimizer make code go fast. C has given undefined behavior a bad reputation, but it's a tool. Zig lets you decide exactly where to opt in or out of the speed/safety tradeoffs.
Illegal behavior is a better name for a code sequence that is guaranteed to panic. There is too muchalready-established meaning around C and C++'s use of the phrase "undefined behavior"
That sounds reasonable. I agree that overflow is often a bug (and in GCC can use -ftrapv to enforce that view). But overflow is also frequently what you want in algorithms that deal with counters or differences of sums. Maybe point out that there are well-defined operators available in Zig as well?
I'm not immediately seeing how non-wrapping arithmetic can enable significant optimisation. What could be faster than an integer add? If you have an example, I would be very interested (the classic "infinite loop" example is not particularly meaningful in my view).
I always assumed that C left this undefined mostly to support non-two's complement machines, which should probably not be a concern anymore. That's the only explanation I can come up with that explains why unsigned arithmetic is well-defined, but not signed arithmetic.
Andrew does post YouTube videos of his coding sessions which teaches me a lot of Zig and gives me pointers on using Vim as an overall IDE https://www.youtube.com/user/superjoe30
Great project, but it has had more than one major discussion on HN in the last year, which makes this submission a dupe (see https://news.ycombinator.com/newsfaq.html).
59 comments
[ 3.6 ms ] story [ 104 ms ] threadEven as someone who follows zig closely (from a distance), I was glad to read that front page again to day to refresh my memory about:
* Cross-compiling is a first-class use case
* Zig Build system
Also, IMO Zig has some of the most exciting WASM related stuff going on in my limited experience as an outsider (to WASM). Following Zig's development of WASM capabilities has taught me more things with less confusion.
* [interacting with the DOM from Zig](https://shritesh.github.io/zig-wasm-dom/)
* [zig fmt in the browser](https://shritesh.github.io/zigfmt-web/)
* [implementing the WASI target](https://twitter.com/shritesh/status/1123049218086666246)
One point I noticed: under "Small, simple language", you mention that Rust and C++ have operator overloading. But D does as well:
https://dlang.org/spec/operatoroverloading.html
> Robust - behavior is correct even for edge cases such as out of memory.
> Optimal - write programs the best way they can behave and perform.
> Maintainable - precisely communicate intent to the compiler and other programmers. The language imposes a low overhead to reading code and is resilient to changing requirements and environments.
[1] https://ziglang.org/documentation/master/
In other words, you could say they TAKE OFF EVERY ZIG.
It'll be especially well suited for this kind of thing because the self-hosted compiler is a long running process that watches files for changes and rebuilds incrementally. [1 minute demo of early progress](https://www.youtube.com/watch?v=b_Pm29crq6Q).
Right now progress is blocking on [The Coroutine Rewrite Issue](https://github.com/ziglang/zig/issues/2377).
[0]
[1]
[2]
(FWIW, M↓ is supposed to be lightweight enough that it's readable inline. The links can get a little long, but I think it's not too hard to skip, and it does have the upshot of not making you have to match up citation numbers. But you're right that the numbered format is more common among posters.)
Personally I like the lightweightness of HN comments, it forces the content to be good over everything else.
When the raspberry pi 3 hardware boots, it jumps to 0x0. So this is the part where the bootloader loads the new kernel image into memory... starting at address 0!
vs
> (int*)0
They sure make you pay though the nose to cast in zig -- maybe a good thing?
So when you create a pointer out of thin air, you have to inform the type system precisely what kind of pointer it is. That's why it is so much more gnarly than C, it wants you to be explicit.
In a bare-metal environment, there's nothing saying that physical address zero must be unused by the hardware designer.
So I think it's quite the opposite: There's no requirement that address 0 must be unoccupied in any situation, it just so happens that many operating systems choose to leave it unmapped as a debugging aid for developers.
Zig's program source code is extremely readable. I love it !!
I'll take S<T, U<int, long>, W<int>> over S!(T, U!(int, long), W!int) any day.
I'm pretty sure I'm in the minority with that opinion though.
In all seriousness, what questions does it raise? HN has a long history of featuring old and new languages on the front page and often you'll bump into language designers and researchers.
I could be wrong, but I recall the front page featuring more esoteric languages/ideas in its early days. (My username doesn't reflect how long I've been here BTW)
> but can't help but think the time would be better spent adding feature Y to language X, but didn't mean to start anything :-)
When people create new languages, the premise is rarely along the lines of: "I like this language, but if it only had this feature." The truth is there are a whole slew of very legitimate reasons for creating a new language. Many of those reasons are predicated on the idea that the mainstream alternatives have too many wrong features and/or it would be difficult-impossible to fix those flaws by adding new features. As you already know, it's a lot harder to remove a feature from a mainstream language than it is to introduce a new feature, so languages tend to become more complicated as time goes on. New languages tend to provide a clean slate and opportunity to learn from the mistakes of its predecessors.
Another reason to create new languages: New languages often act as the test bed for ideas that eventually end up in mainstream languages. As mainstream languages mature, they rely on more experimental languages to introduce ideas so they can be tested. The only way to test these ideas is to have people write programs in these languages and study the outcome. With that being said, if it wasn't for the experimental languages, mainstream languages would not likely have things like objects, or lambda functions, continuations, type inferencing, polymorphic type systems, etc.
So, if you find yourself being down-voted for asking questions like, "why don't you just add feature Y to language X", it's because you're in the wrong venue. You're not the first to ask the question. I'm not the first to answer it, so you're bound to ruffle feathers.
Now, I work on Zig during the day and I'm training with my brother for our first marathon on nights & weekends. I'm really thankful for you and others' support so that I can do this.
Still in NYC for 1 more year, but my girlfriend is finishing up her master's and looking for Ph.D. programs in California.
Maybe Zig has something in this department, too.
Parameters can have `noalias` on them. This is [currently undocumented](https://github.com/ziglang/zig/issues/1521) and [not yet safety checked](https://github.com/ziglang/zig/issues/476) and there is an [open area of research considering doing it the opposite way](https://github.com/ziglang/zig/issues/1108). Provided that it could be safety-checked, opt-in aliasing has the potential to make Zig even faster. As far as I'm aware, this is currently the only way in which Rust could potentially outperform Zig (and C).
I know that's the theory, but with few exceptions this doesn't seem to have panned out in reality anywhere and C is usually still the gold standard when it come to performance. How many more decades until we get these sufficiently smart compilers?
This irks me especially badly since the underlying hardware operations are almost always well-defined, but in my "high-level" language I constantly have to worry that I missed something and maybe the compiler will "optimise" my + into something other than addition.
Is there a fully well-defined addition operator in Zig? What about a well-defined shift operator? This might make me, as a professional C programmer, more interested in a new C-like language.
[0] https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins...
[1] https://www.gnu.org/software/autoconf/manual/autoconf-2.63/h...
I don't imagine it's possible to check using a static assert, either.
https://gcc.gnu.org/onlinedocs/gcc/Pragmas.html#Pragmas
Would you feel better if it was called "illegal behavior"? In the safe build modes of Zig, integer arithmetic, shifting, wrong union field access, etc is 100% well-defined. Integer overflow is defined to panic. Unless of course you use one of the wrapping arithmetic operators; in these cases it is defined to do wrapping arithmetic.
Integer overflow is usually a bug. If it weren't illegal behavior, zig wouldn't be able to help you catch the bug. That's why clang's integer arithmetic sanitizer only works for signed ints. It's much better for programmers to specify their intent precisely, which is why Zig has different operators for wraparound and assert-it-doesnt-overflow.
Undefined behavior in the unsafe modes is what lets the optimizer make code go fast. C has given undefined behavior a bad reputation, but it's a tool. Zig lets you decide exactly where to opt in or out of the speed/safety tradeoffs.
I'm not immediately seeing how non-wrapping arithmetic can enable significant optimisation. What could be faster than an integer add? If you have an example, I would be very interested (the classic "infinite loop" example is not particularly meaningful in my view).
I always assumed that C left this undefined mostly to support non-two's complement machines, which should probably not be a concern anymore. That's the only explanation I can come up with that explains why unsigned arithmetic is well-defined, but not signed arithmetic.
Since when can you throw exceptions in Go?
Most recently: https://news.ycombinator.com/item?id=19610199
Other big ones: https://hn.algolia.com/?query=Zig%20points%3E30&sort=byDate&...
Here it is from a few days ago: https://web.archive.org/web/20190430121340/https://ziglang.o...