News for hackers. Stuff that matters.
Re:Zig, parser combinators, and why they're awesome by Jakobeha on Wednesday March 10, 2021 @07:12PM (#26418408)
I see a lot of articles posted on HN about Zig. What's so special about Zig, and how does it fill its own niche with other languages like Go and Rust?
Re:Zig, parser combinators, and why they're awesome by lhorie on Wednesday March 10, 2021 @09:53PM (#26419644)
As far as I know, zig is the only language that is able to output binaries on par in size w/ C (a hello world in zig is about the same size as a C one, whereas most other languages can only manage at a minimum an order of magnitude bigger binaries, sometimes several orders of magnitude). Zig interops cleanly w/ C ABI and C toolchains, can also cross compile AND can cross compile C proper. You can even drop all the way down to asm (standard C technically doesn't support this).

I often refer to zig as a "very sharp knife": it's "cool" for new languages to have more safeguards to protect you from yourself, but Zig feels a bit like it goes in opposite direction in the sense that it exposes the underlying plumbing more than most languages. For example, Go and Rust memory allocations and memory layout are fairly opaque; in zig you can control it idiomatically with obsessive precision.

But unlike C, zig offers a host of safety features, like integer overflow checks, compiler-checked optionals and exhaustive switch, as well as a well behaved compile-time system, and a bunch of syntactical sugar ("method" syntax, if/while/block/return expressions, etc).

And unlike C++, zig is a very small language.

Re:Zig, parser combinators, and why they're awesome by pcwalton on Wednesday March 10, 2021 @09:56PM (#26419664)
It's possible to make very small Rust binaries: https://github.com/johnthagen/min-sized-rust 8kB for that Rust example, compared to 16kB for my optimized C hello world compiled with GCC. (Not that I think it makes a difference to anything.)

Furthermore, how are Rust memory allocations and layout "fairly opaque"?

Re:Zig, parser combinators, and why they're awesome by lhorie on Wednesday March 10, 2021 @10:08PM (#26419732)
For example, usually it's not obvious when memory is being freed. I recall a thread about esbuild where the author was saying they had better GC perf from go due to GC happening in a thread whereas in Rust it didn't and it was not clear how to make that happen or if it was even possible.

In zig, you can use an arena allocator, you can free things piecemeal while using an arena, you can free the arena on program exit or in a thread, you can enforce a stack allocator, have multiple allocators, etc and because of the orthogonality of the Allocator interface, most of this knowledge is something you can probably pick up within the first 2 hours of zig (assuming you know C).

Re: edit about rust binary size. When I say zig is on par w/ C in terms of binary size, I mean I get the small binary with the basic `zig build-exe hello.zig -O ReleaseFast --strip` command, without any attempts at optimization. Do you know if this 8kb number includes the UPX optimization? If so, I'm calling shenanigans :)

Re:Zig, parser combinators, and why they're awesome by pcwalton on Wednesday March 10, 2021 @10:29PM (#26419855)
You can use arena allocators in Rust: bumpalo is popular. And it's easy to send objects off to a separate thread to be destroyed if that's what you desire: just send them over a channel to another thread (though this is really something that the malloc implementation should do internally if it's a win). There's an RFC for multiple allocators that has had some implementation work done lately: https://rust-lang.github.io/rfcs/1398-kinds-of-allocators.ht...

I don't believe that that 8kB number is with UPX, but again, even if Rust produces smaller binaries than C, it doesn't matter. Most users would prefer faster compilation times with codegen-units over a few kB smaller binaries, for instance, as long as there's a reasonable way to get the smaller binaries for those who need them.

Re:Zig, parser combinators, and why they're awesome by lhorie on Thursday March 11, 2021 @12:19AM (#26420559)
I mean, I don't want to speak for the esbuild author, but he did mention that his rust implementation ran into a number of issues[0], one of them being related to making lifetime stuff happy with concurrency. Judging from other recent rust threads, I'm not super convinced that "easy" is necessarily a fair representation of how it feels to do not-quite-bog-standard-functional-stuff w/ rust.

[0] https://news.ycombinator.com/item?id=22336284

Re:Zig, parser combinators, and why they're awesome by Dylan16807 on Wednesday March 10, 2021 @10:59PM (#26420046)
"A striped binary built this way is around 8KB."

It's before UPX.

> I mean I get the small binary with the basic `zig build-exe hello.zig -O ReleaseFast --strip` command, without any attempts at optimization.

You could set up all these things in just a few minutes, so it's not a very big deal. If you don't mind 20KB of string formatting code then you don't have to make "any attempts at optimization" either.

Re:Zig, parser combinators, and why they're awesome by lhorie on Wednesday March 10, 2021 @11:49PM (#26420389)
> If you don't mind 20KB of string formatting code

So this here is sort of why I brought up binary size. I know hello world size doesn't really say anything about real world, but as I was looking at different languages, a common theme was this defensive "well what d'ya expect from a thing that has [list of features]" tone when the question of binary size got brought up and people didn't know how to make it smaller. A normal rust build has a similar feel. The 8kb binary link above reads a bit like a hacking adventure to unravel the mysteries of yonder.

When I read stuff like this

    By using a C entry point (by added the #![no_main] attribute) , managing stdio manually, and carefully analyzing which chunks of code you or your dependencies include, you can sometimes make use of libstd while avoiding bloated core::fmt.

    Expect the code to be hacky and unportable, with more unsafe{}s than usual. It feels like no_std, but with libstd.
I'm undoubtedly awed at the cleverness of it all, but it's clearly way off the beaten path.

I should note that in addition to the zig build command being guessable by a newbie reading through --help, the hello world code itself is also the idiomatic thing a newbie would've reasonably written. And there's really no need for "air quotes", I really put no effort whatsoever in optimizing: I didn't even use `-O ReleaseSmall`

Among all the languages I looked at, Zig was somewhat unique in taking a default stance of proactively using compile time as a tool to take stuff away from the binary (in a sort of saint-exupery way).

I'm sure with enough effort it's possible to bring down binary sizes for most languages, but not many languages do this with the relentlessness that zig does out of the box.

Re:Zig, parser combinators, and why they're awesome by Dylan16807 on Thursday March 11, 2021 @12:33AM (#26420633)
> So this here is sort of why I brought up binary size. I know hello world size doesn't really say anything about real world, but as I was looking at different languages, a common theme was this defensive "well what d'ya expect from a thing that has [list of features]" tone when the question of binary size got brought up and people didn't know how to make it smaller.

Well, what do you expect? How much size does printf add to a Zig binary?

> When I read stuff like this

You can get the vast majority of the size savings without any of that stuff. This is someone trying to find the absolute minimum, starting with very practical suggestions before getting into itty bitty weeds. I'd suggest pretending the no_main and no_std sections don't exist.

Getting down to 50KB or 30KB is just a matter of telling the compiler to optimize for size and stripping unwind information.

If you want to keep all the unwind code and information I'm not sure how much space it takes.

> with enough effort

I will note again that the compiler settings in this repo, while they may be in multiple places, are still a very small one-time effort for a program.

Re:Zig, parser combinators, and why they're awesome by lhorie on Thursday March 11, 2021 @01:28AM (#26420926)
Well, it's not so much about expectations about byte counts per se. YMMV but in my experience, for whatever reason the relative size of an average program happens to correlate with how big and complex a project gets as a function of its growth. For example, the Factor distribution is some 700MB and unsurprisingly a hello world image is also huge. A while back I also saw one analysis about jquery/vue/angular/react sites and curiously framework size was also a good predictor of average app size in the wild.

So I use the size metric as a coarse proxy for "complexity required to accomplish the task at hand". And if one is to believe the mantra "to be fast, do less stuff", then my instinct is to look for technologies whose proxy metric (i.e. idiomatic hello world size) is small.

Maybe there are better ways to measure this, but so far this heuristic has worked for me.

> How much size does printf add to a Zig binary?

It depends, because comptime. Basically, it emits different code depending on the types of the params being passed in. For hello world, it wouldn't include itoa logic, for example. The irony here of course is that zig could in theory compile to a very very large binary if it had a very very large number of printf calls, all with different permutations of types. But the thing is that to a zig developer, it's clear that this is explicit static polymorphism getting compiled into a plethora of monomorphic callsites. One could implement the equivalent of go's `interface {}` underlying {type, value} tuple and have a single polymorphic function at runtime if that's what they wanted. But this same argument about how it would require someone manually implementing such a thing goes both ways: it also means that most other possible things are likely not going to be hanging around quietly adding complexity under the rug (not saying this is the case w/ rust, but it is with various other systems).

Re:Zig, parser combinators, and why they're awesome by volta83 on Thursday March 11, 2021 @06:01AM (#26422687)
> But the thing is that to a zig developer, it's clear that this is explicit static polymorphism getting compiled into a plethora of monomorphic callsites

To a Rust programmer it is clear that the toolchain defaults are set up to satisfy the 99.99999999% of programmers whose goal isn't to "write the smallest hello world possible".

You can change these defaults in your system config if you don't like them.

Like you mention, one size doesn't fit all.

To me that's one of the main differences between Zig and Rust.

Re:Zig, parser combinators, and why they're awesome by lhorie on Thursday March 11, 2021 @07:50AM (#26423417)
It's also not entirely about clarity of facts per se, but rather which facts. It's clear for a javascript developer that doing NPM install is going to bring in half the universe worth of transitive deps and that they can opt out by writing things by hand.

Most js developers' goals are indeed not to write the smallest hello world, and here we are in a world where people complain of news websites pulling MBs of scripts. As I mentioned, one could conceivably address this by merely picking jquery over react in many cases, for example. There's a predictable sliding scale of performance between using electron, nodegui and qt proper via c++. Etc. All of this is to say: Defaults and base choices matter.

I think in terms of servicing end users, rust and c++ are somewhat unique in that they are relatively complex languages targeting ambitious performance goals, at the cost of more language complexity. That has its own appeal for sure, but I echo esbuild author's sentiment about a language having to be fun for side projects, and for me personally, I like the simple "very sharp knife" variety of technologies

Re:Zig, parser combinators, and why they're awesome by user-the-name on Thursday March 11, 2021 @08:27AM (#26423744)
It's not clear to me.

I'm not a Rust programmer, but I've written several projects where I'm pulling in a large Rust dependency, because the best available library for something is implemented in Rust, and it offers a C interface.

These libraries I've used have been very good, but also, extremely large. Like, over 100 MB .a files. They slow down compilation noticeably just by linking, and while a lot of the size is stripped out during linking, the resulting sizes tend to still be uncomfortably big.

So to me it seems Rust binaries tend to be huge both on the small end large ends of the spectrum, and they are large to the point where it becomes a real problem.

Re:Zig, parser combinators, and why they're awesome by volta83 on Thursday March 11, 2021 @04:41PM (#26429345)
You should open an issue with whoever packages that library.

Nobody expects library consumers to be experts in how to build libraries.

But this isn't any different that depending on a C library, and discovering that the Makefile they are using compiles it with -O0, and makes it super slow.

To a non-C programmer, flipping -O0 to -O3 is wizardry.

---

Point being, you are not a rust programmer, and the defaults that are good for "development" are not good for "shipping" and therefore no good for you. If your library doesn't do this right, open a bug. The library can override this, and a package that builds it should override this.

Re:Zig, parser combinators, and why they're awesome by user-the-name on Friday March 12, 2021 @05:31AM (#26434177)
No, this is a fully optimised release build, built according to official instructions.

Rust code is just very big. This seems to come with the territory.

Re:Zig, parser combinators, and why they're awesome by volta83 on Tuesday March 16, 2021 @05:38AM (#26474649)
> Rust code is just very big. This seems to come with the territory.

As someone that uses Rust every day to program STM32s with 128KB of space... i... disagree...

Rust is the only high level language I know that allows me to customize the language run-time at will, allowing me to provide my own unwinding, threading, memory allocation, ... runtimes, to be able to program tiny machines as if I was just programming any normal one.

With other languages either I can use the standard library implementation, or I can't use the standard library and some language features at all.

With Rust, I can't use the standard library implementation for desktops, but I can just swap its backend by an embedded one, and am still able to re-use all the high level code, libraries from crates.io that use it, etc.

Re:Zig, parser combinators, and why they're awesome by AndyKelley on Wednesday March 10, 2021 @11:24PM (#26420218)
for zig it's 1.8 kB on x86_64-linux with minimal fiddling. i386-windows comes out to 2.5kB.

    $ cat hello.zig
    const std = @import("std");
    pub fn main() void {
          std.io.getStdOut().writeAll("Hello, World!\n") catch {};
    }
    $ zig build-exe hello.zig --strip -OReleaseSmall
    $ zig build-exe hello.zig --strip -OReleaseSmall -target i386-windows
    $ ldd hello
     not a dynamic executable
    $ strip hello
    $ ./hello
    Hello, World!
    $ wine hello.exe
    Hello, World!
    $ ls -hl hello hello.exe
    -rwxr-xr-x 1 andy users 1.8K Mar 10 21:15 hello
    -rwxr-xr-x 1 andy users 2.5K Mar 10 21:15 hello.exe

No min-sized-zig github repository needed.
Re:Zig, parser combinators, and why they're awesome by steveklabnik on Wednesday March 10, 2021 @11:57PM (#26420425)
I work in embedded these days, commented on this topic on Reddit a few days ago: https://www.reddit.com/r/rust/comments/m0irjk/opinions_on_ru...
Re:Zig, parser combinators, and why they're awesome by anderspitman on Wednesday March 10, 2021 @10:02PM (#26419698)
Not parent, but from my perspective implicit RAII might fall into this category, though I suppose that's specific to deallocation. Zig also requires you to pass an allocator to any function that requires dynamic allocation, which while this could be considered a bit extreme, is certainly less "opaque".
Re:Zig, parser combinators, and why they're awesome by FlashBlaze on Wednesday March 10, 2021 @10:07PM (#26419731)
Would very much like to read your thoughts on V[0]

[0] https://vlang.io/

Re:Zig, parser combinators, and why they're awesome by lhorie on Wednesday March 10, 2021 @11:10PM (#26420104)
Honestly, I was put off by the early marketing hullabaloo, so I haven't looked closely. What's most problematic in my mind is that from what I've seen, I don't feel that the V lead is as forthcoming about issues and limitations as other project leads are. I'd much rather talk to a project lead that will give it to me straight if their stuff doesn't work.

From a technical perspective, my understanding is that V similar to Nim, in the sense that it compiles to C source code. That's fine and all, but IMHO, zig has a huge leg up in this area because it does first class cross compilation of C source code to binary form. To my knowledge, no other tool does this (other than maybe cosmopolitan, if you ignore everything outside posix...)

If I were to use V, I'd probably end up using `zig cc` as the `cc` for it

Re:Zig, parser combinators, and why they're awesome by lelanthran on Thursday March 11, 2021 @09:44AM (#26424484)
> zig has a huge leg up in this area because it does first class cross compilation of C source code to binary form.

What's the advantage of this? Compilation speed?

Doesn't that then mean that zig can't gain compiler improvements the way using an external compiler can? For example, if C is the intermediate language for $HIGH-LEVEL-LANGUAGE, then $HLL benefits every time that the specific C compiler being used is upgraded.

Re:Zig, parser combinators, and why they're awesome by lhorie on Thursday March 11, 2021 @11:03AM (#26425453)
The advantage is cross compilation. Gcc and friends are notoriously difficult to setup for cross compilation (so much so that some don't even bother trying and either only offer source or just compile from different machines running the target platforms, and even this can be a bit of an ordeal)

Zig uses LLVM under the hood so it does benefit from LLVM upgrades. Also, there's devils in the details. For example, the copy ellision thing is something that required deliberate implementation; it doesn't just come for free if you're naively emitting C.

Re:Zig, parser combinators, and why they're awesome by lelanthran on Thursday March 11, 2021 @01:34PM (#26427328)
Thanks, that's a good answer.

> For example, the copy ellision thing is something that required deliberate implementation; it doesn't just come for free if you're naively emitting C.

I don't know what copy elision is. Can you explain that too?

Re:Zig, parser combinators, and why they're awesome by lhorie on Thursday March 11, 2021 @03:15PM (#26428482)
You can read more about it here: https://github.com/ziglang/zig/issues/2765
Re:Zig, parser combinators, and why they're awesome by MaxBarraclough on Thursday March 11, 2021 @06:57AM (#26423087)
How does V handle reference cycles?

> Most objects (~90-100%) are freed by V's autofree engine: the compiler inserts necessary free calls automatically during compilation. Remaining small percentage of objects is freed via reference counting.

> The developer doesn't need to change anything in their code. "It just works", like in Python, Go, or Java, except there's no heavy GC tracing everything or expensive RC for each object.

So how does V handle reference cycles? A partial solution based on static-analysis (autofree) isn't going to catch all reference cycles, by definition, and automatic reference-counting won't catch reference-cycles either.

I have to agree with lhorie's comment: I get the impression I'm only getting half the story.

The Nim folks also often seem to skim over the question of reference cycles.

Re:Zig, parser combinators, and why they're awesome by cb321 on Thursday March 11, 2021 @07:54AM (#26423450)
If the Nim folks seem to skim over this, it is probably because of the large diversity of options & concerns. You can --gc:none or --gc:arc to blow off the reference cycle problem, but the default gc handles it fine (and --gc:orc and --gc:markAndSweep and --gc:boehm and ...). Here is a nice, recent blog post about ORC [1].

So, in this case the skimming is just an "abbreviated story" which seems reasonable when the full story is long (the Nim project has been around since before 2008...).

For V, well it did have a huge initial hype/propaganda cycle and is also quite young, and I believe the V author made a bunch of extreme claims before publicly releasing the code for scrutiny/corroboration. So, that may be much more suspicious.

[1] https://nim-lang.org/blog/2020/12/08/introducing-orc.html

Re:Zig, parser combinators, and why they're awesome by MaxBarraclough on Thursday March 11, 2021 @09:59AM (#26424640)
You're right, ORC does look interesting, I was too dismissive. Their conventional GCs are way behind the state of the art though (e.g. in HotSpot), but I don't really blame them for that, implementing a cutting-edge GC is an mammoth task and extremely technically demanding.

From your linked article:

> it turns out there are lots of ideas that the GC research overlooked. Exciting times for Nim!

I wish them luck, this is a field where great progress has been made over the last decade, hopefully more to come. If they really can beat the JVM head-on, that would be very impressive, especially if they do so while using C as an intermediate language.

Re:Zig, parser combinators, and why they're awesome by cb321 on Thursday March 11, 2021 @10:20AM (#26424918)
Something often overlooked in comparisons is "The many dimensions of beat". In some ways ORC probably already beats the best JVM while in others it may never. The best benchmark is, as always, one's own code. :-) I've found Nim quite efficient, though.

The one time when I had trouble with Nim's GC perf was years ago implementing Wolfe Garbe's Symmetric Delete spell checking algorithm [0]. Even then, it worked with nim c --gc:boehm but blew up with others. So, there was nothing stopping me from doing it in Nim. This was my initial "in volatile RAM" solution before I went to a fully persistent on-disk memory mapped solution [1]. SymDel is an algorithm particularly demanding of prog.lang run-time basics as explained in that link. I've come to think of it as a good stress test. { Not the only one, of course :-) } I wonder how well Java's GCs would fare.

[0] https://github.com/wolfgarbe/symspell

[1] https://github.com/c-blake/suggest

Re:Zig, parser combinators, and why they're awesome by abnercoimbre on Wednesday March 10, 2021 @07:24PM (#26418512)
If you can spare 60-90 minutes, I hosted [0] a conversation with the creator of Zig, as well as Odin, plus a former co-worker who's a compiler engineer.

They're all vibing in the same space that try to fill the niche we believe is missing.

[0] https://media.handmade-seattle.com/the-race-to-replace-c-and...

Re:Zig, parser combinators, and why they're awesome by kristoff_it on Wednesday March 10, 2021 @08:00PM (#26418789)
That's a great window on programming languages that exist in the systems programming space but that are not Rust, C or C++.
Re:Zig, parser combinators, and why they're awesome by tiddles on Thursday March 11, 2021 @07:41AM (#26423367)
Thank you for doing this!

I've listened to this and a few other episodes with Andrew and Ginger Bill, and they're very interesting, I highly recommend them.

Re:Zig, parser combinators, and why they're awesome by anderspitman on Wednesday March 10, 2021 @09:57PM (#26419670)
I've written a decent amount of Rust and Go. The reason Zig is on my watch list is because I see it as a potentially better (ie faster) Go, or C+=1. Go handles most of my needs, but the way I write it tends to involve a decent amount of manual resource management (mostly mutexes), so I don't see the manual memory management in Zig as a big downside.

Rust is a great language, and I love it, but it's hard for me. Writing in Rust reminds me a lot of test-driven development. It gives me such a great feeling of safety and control over your process, but at the end of the day it can be very tedious. The real killer is when I'm trying to prototype. If I don't already know what my interfaces are going to look like, Rust really slows me down. Compile times don't help here either.

If I were implementing a well-known protocol and had a general idea of how to architect it, or just really needed it to be rock solid, I would strongly consider Rust first. I've been working on a lot of protocol design the last couple years so it's been more prototype-heavy.

Note that most of my Rust experience involved pre-async/await asynchronous networking code. I'm sure it would be a better experience for me now. I should also note that programming in Rust yields some very magical moments, such as parallelizing loops by changing a single line. It's a special language, and not going anywhere. I hope to find reasons to use it again in the future.

EDIT: Oh, another place Zig may have a big advantage over Go is binary sizes, particularly for things like WebAssembly.

Re:Zig, parser combinators, and why they're awesome by volta83 on Thursday March 11, 2021 @06:20AM (#26422822)
> The real killer is when I'm trying to prototype. If I don't already know what my interfaces are going to look like, Rust really slows me down.

This requires practice, but given the choice, competitive programmer teams picking Rust do quite well in competitions (ICFP has been won by teams using Rust 3 years in a row, and in the last 3 years, two teams in each year's the top 3 used Rust): https://www.reddit.com/r/rust/comments/ctzmo2/icfp_2019_prog...

There are teaching materials for competitive programming with Rust, you might want to check those. I think they are a good way to learn how to "prototype" in Rust.

It's different enough from other languages that this is a skill that must be actively learned :/

Re:Zig, parser combinators, and why they're awesome by anderspitman on Thursday March 11, 2021 @09:41AM (#26424450)
I have no doubt it can be learned, and I've tried to get over the hump multiple times, but still don't feel as comfortable with Rust as I do with every other language I've worked in, even those I've only spent a few hours in.

It's all about tradeoffs, and at a certain point you have to question whether the academic assurances offered by Rust are worth the complexity, given the problem at hand. As I said, it's obviously worth it for some problems, but I don't think it is for all problems. Which is great! I think the world would be boring if there was one language to rule them all.

Re:Zig, parser combinators, and why they're awesome by volta83 on Thursday March 11, 2021 @04:38PM (#26429310)
feel you, just pointing out that trying competitive programing and their resources might give you a different point-of-view to attack the issue

but like you mentioned, its always nicer if there is no "issue" to be learned in the first place

Re:Zig, parser combinators, and why they're awesome by pron on Thursday March 11, 2021 @07:45AM (#26423384)
Zig, like C, C++, Ada, and Rust -- but very much unlike Go -- is a low-level programming language, i.e. one that gives you virtually full control over implementation details such as function dispatch and memory management. I would say that Zig is the first (more-or-less) known low-level language that is revolutionary in its design. Rust adopts the C++ (and also, arguably, Ada) philosophy of a low-level language that attempts to appear high-level, and ends up being very complex. I would say that C++, Ada, and Rust are all easily among the top five most complex programming languages in software history. On the other hand, you have C, which is "simple" in the sense that it has few features, but is extremely unsafe.

Zig offers a completely new beast, and I'd say a vision for how low-level programming can be done. It is a very simple language -- a C/C++/Rust programmer can probably fully learn it in a day or two -- and yet it is about as expressive as C++/Rust, and much safer than C++. It does that with a single general partial evaluation feature called "comptime" that replaces, rather than augments, generics, traits, macros, while maintaining their capabilities but being arguably simpler than all of them.

Like Rust, Zig places a very high emphasis on correctness, but its approach is different. While safe Rust eliminates all undefined behaviour, safe Zig eliminates many/most, leaving others up to detection via simple testing. What Zig lacks in sound guarantees, it makes up for in being easy to understand, analyse and test.

Zig also has an exceptionally good tooling story around incremental compilation and cross compilation.

In short, I would say Zig offers a completely novel approach to low-level programming that would appeal to those who value a simple language. While Zig and Rust do target a similar niche, I believe they'd attract programmers with very different aesthetic preferences.

Re:Zig, parser combinators, and why they're awesome by logicchains on Thursday March 11, 2021 @07:05AM (#26423137)
For ultra-low-latency programming, you generally want to avoid dynamic memory allocation on the hot path. Instead it's common to use a slab allocator, from memory on the stack or that was dynamically allocated on startup, to continuously reuse the same memory. E.g. when a web request comes in, allocate all temporary per-request state from a single bump allocator, then after the request has finished just "free" everything by setting the "allocateFromHereNext" pointer back to the start of the allocator's buffer. This is not only the fastest means of allocation/deallocation (just bump a pointer), but also means that new requests can reuse the same memory addresses (the allocator's internal buffer), achieving better cache locality as the memory's already in cache.

Zig is ideal for this as all stdlib functions that allocate take an allocator as a parameter (so there's no hidden allocation), and the stdlib provides a bunch of allocators. This is even better than C++, where some functions like std::stable_sort unavoidably allocate memory. Rust doesn't have much support for custom allocators in the stdlib although it's being worked on, but it's more difficult to implement in Rust as the compiler must be able to ensure that the allocator (or at least its buffer) outlives all the things being allocated from it.

Re:Zig, parser combinators, and why they're awesome by nmfisher on Wednesday March 10, 2021 @08:50PM (#26419166)
I'd be interested in "Why Zig over Rust?".

Having dabbled with Rust, it seems to be the perfect solution/replacement for C/C++. I'm not clear why I should bother with an alternative.

Re:Zig, parser combinators, and why they're awesome by socialdemocrat on Wednesday March 10, 2021 @10:35PM (#26419892)
I have spent some time with Rust and written some non-trivial Zig code (a simpler assembler). My simple take-away is that Rust is simply too complicated.

I spend some time on other technologies on occasion. I could get into Zig fairly quickly and do some useful stuff with it.

With Rust it felt like I had to really decide on some significant time investment to be able to get anything done. It really reminds me a lot of Haskell. Those kinds of pure, elegant languages which are awesome once you grok them, but which is never really going to be used apart from in a small niche because they are too hard to learn from an average developer with limited time on his hands.

Rust and Haskell is more like the languages I looked for when I was younger. When I had these utopian visions of THE best programming language. I have long lost any belief in that. I do think strong type systems are helpful, but I also think they tend to get overhyped and overrated.

I am with Rob Pike, one of the Go designers on this. Writing correct code is a lot about understanding and being able to reason about that code. A simpler language makes it easier to reason about code and understand it. That makes it more likely that you make the code correct or is able to maintain and fix it.

I do believe this complexity barrier begins at different places for different people. But for me I think Rust is too complex. Knowing myself I would get back to 3-4 weeks old code and wonder what the hell I wrote.

If you get into that situation you are likely to make mistakes. This is what I believe developers often forget when chasing down the BEST tool. That ultimately it is your brain that is supposed to solve problems not the tool. If a tool solves some problems but reduce your brains ability to do its job, then the tool isn't really an aid.

To be honest I am not actually certain if Zig has hit the sweat spot either. Go is quite good. You can pick up quite old Go code and still read it with relative ease.

Zig is definitely not as easy as Go to read. I feel like I have to wait until a 1.0 release before passing judgment. Some of the issues I felt I had with Zig is down to lack of documentation and rough edges in the standard library.

Re:Zig, parser combinators, and why they're awesome by dm3 on Thursday March 11, 2021 @03:20AM (#26421613)
I really enjoyed your comment. Probably because I've been thinking the same for a long time now. I've had to learn and write a lot of C++ in the past year and the only way to stay sane is to use as small subset of the beast as possible. In many ways Rust is a better C++ - no undefined behaviour, no lvalues/rvalues/xvalues/..., complicated move semantics, tooling, etc. Rust feels like a nice subset of C++ with additional safety features on top.

However, once people reach for C, C++, Rust or Zig - performance is on the line. To push the maximum out of the program we need to do as much compile-time programming as possible. C++ template meta-programming language is Turing-complete but extremely hard to learn and effectively program with. Rust compile-time programming is evolving - two sorts of macros and a Zig-comptime-like `const fn` feature. What I like about Zig's approach is summarized well by pron[0].

[0]: https://news.ycombinator.com/item?id=22112382

Re:Zig, parser combinators, and why they're awesome by xtian on Wednesday March 10, 2021 @09:09PM (#26419324)
Re:Zig, parser combinators, and why they're awesome by linkdd on Wednesday March 10, 2021 @09:53PM (#26419637)
> it seems to be the perfect solution/replacement for C/C++

Many languages tried for 50 years to replace C without success.

While Rust brings many improvements for low-level development on classical architecture, simplifying hard problems (especially memory safety), there is still a HUGE number of platforms (embedded ones mainly?) where C and even Assembly are still relevant.

Believing that any language will burry C/C++ is ignoring what C/C++ are.

Re:Zig, parser combinators, and why they're awesome by cageface on Wednesday March 10, 2021 @10:39PM (#26419918)
It looks like Zig requires manual memory magagement, right? That seems like a pretty big downside compared to GC or the Rust approach.
Re:Zig, parser combinators, and why they're awesome by diragon on Thursday March 11, 2021 @01:59AM (#26421122)
True. That is however countered by a vastly simpler language. Language support for deferred cleanups[0] helps a bit. Also the GeneralPurposeAllocator[1] contains memory safety debugging features that make analyzing such bugs bit nicer.

IMHO it's a significant net gain over something like Rust because of the simplicity for most of the problems out there. I got 99 problems but needing absolute memory safety ain't one.

[0] https://ziglang.org/documentation/master/#defer

[1] https://ziglang.org/learn/samples/#memory-leak-detection

Re:Zig, parser combinators, and why they're awesome by linkdd on Wednesday March 10, 2021 @10:42PM (#26419936)
That's because the Zig approach is "no hidden control flow".

Everything in Zig is explicit, this is not a downside, this is a feature of the language.

Choose the tool that best fits your needs.

Re:Zig, parser combinators, and why they're awesome by cageface on Wednesday March 10, 2021 @10:44PM (#26419949)
That's fair but that does mean that I wouldn't consider it unless I really needed that kind of control. That's a niche few devs need to worry about.
Re:Zig, parser combinators, and why they're awesome by mtzet on Thursday March 11, 2021 @02:53AM (#26421455)
Well the choices so far seems to be manual memory allocation, RAII or GC. The complexity of C++/Rust indicates that RAII is certainly not a panacea either. GC offers distinct trade-offs as well.

Zig takes a stab at the problem by trying to make manual memory management more ergonomic. I've been pleasantly surprised at how easy I found it to do tasks in Zig I would otherwise have used a scripting language like Python for.

If go's fast GC is taking a stab at C's territory, then I think Zig is taking a stab at the managed runtime's territory. Ultimately the judge is still out.

Re:Zig, parser combinators, and why they're awesome by linkdd on Wednesday March 10, 2021 @10:52PM (#26420006)
One advantage of that kind of control is that your code does not depend of the implementation of any abstraction (except the operating system if any?) since everything is written "in stone".

I also think it makes a great learning tool, mainly to understand:

  - how a GC or memory management is/should be implemented
  - what pain points they solve (or: why they are important)
When you don't have to think about the abstractions but only your code, it prevents the student from being confused about what happens when.

But I would not use it in production, just like you said, because in production, I want to maintain as little code as possible, and delegate the complexity to other better tools/people.

[dead]
Re:Zig, parser combinators, and why they're awesome by dunefox on Thursday March 11, 2021 @05:31AM (#26422462)
Like what?
[dead]
Re:Zig, parser combinators, and why they're awesome by dunefox on Thursday March 11, 2021 @06:45AM (#26422989)
But that's unrelated to "social justice", isn't it? It is idiotic nonetheless.
Re:Zig, parser combinators, and why they're awesome by enriquto on Thursday March 11, 2021 @12:41AM (#26420673)
> Rust, it seems to be the perfect solution/replacement for C/C++

If you are the sort of person who writes "C/C++" you'll have some trouble understanding the purpose of Zig... maybe start by grokking why the expression "C/C++" is nonsensical?

Re:Zig, parser combinators, and why they're awesome by flohofwoe on Thursday March 11, 2021 @07:16AM (#26423212)
Argh I'm so tired of this "technicality". Yes, technically C and C++ are different languages, and C is not a subset of C++ (which is a pretty big problem btw). But C++ has been derived from C, then forked its C subset into an incompatible dialect, while not fixing any of C's problems (which would've been an actually good reason to not call it "C/C++"). I think it's fair to call C++ "C/C++", because it will always be a confusing mishmash of C and the features that C++ added on top.

Sorry about the rant.

Re:Zig, parser combinators, and why they're awesome by thraway123412 on Thursday March 11, 2021 @11:01AM (#26425443)
The problem is that we have no idea what you're talking about when you say C/C++. For you it seems to be C++, for someone else it might be both or it might be "one or the other but I don't know which." For yet someone else it might be really just C.

If you were to think that Rust is a good replacement for C++, why not just say that Rust is a good replacement for C++? That makes it clear what you mean, and thus the obvious follow-up: a lot of people would like a replacement for C, which is arguably not what Rust is.

And this is very on-topic for a discussion where someone asked "why Zig over Rust?" Zig is arguably closer in spirit to C than Rust is.

When you say Rust is a good replacement for C/C++, a lot of people read it as if you were treating C and C++ as one language and that Rust is a good replacement for both. It should not be hard to see why this is very controversial, given that they are very different languages and people tend to like one and dislike the other. It's going to be very hard to please both camps.

Re:Zig, parser combinators, and why they're awesome by flohofwoe on Thursday March 11, 2021 @11:16AM (#26425619)
I agree, and my reply was more in reaction to the snark in the reply above. Even a lot of C++ programmers don't know that C is actually quite a different language than the "subset of C++ that kinda looks like C" and are surprised when they see "proper" C99 code for the first time. If even "experts" don't quite know the differences between "actual C" and the "C-like subset of C++", it's a bit much to ask the same of people who only have casual knowledge of "C/C++".
Re:Zig, parser combinators, and why they're awesome by enriquto on Thursday March 11, 2021 @02:54PM (#26428269)
You are right, my message did come out as snarky... sorry about that, it was not my intention. I agree with you, the Zig language appeals precisely to those people who enjoy proper, modern C, and want a better language. It does not appeal at all to people who want "a better C++". Thus I was suggesting to understand the distinction between C and C++ as the main point.
Re:Zig, parser combinators, and why they're awesome by steveklabnik on Thursday March 11, 2021 @11:22AM (#26425701)
Not everyone agrees with the line "Rust is a C++ replacement, not a C replacement." I work with a bunch of C folks who never considered C++, but love Rust now.

It's sort of the same thing as people who say "Go is a C replacement." That is a thing some people say, but to me, it never really made sense.

The key is, what a language means to the person who uses it can differ between people. And what benefits they see out of another language can differ between people.

Re:Zig, parser combinators, and why they're awesome by thraway123412 on Thursday March 11, 2021 @06:58AM (#26423094)
Look bro I like Haskell so Haskell is a perfect replacement for Scheme/Java.
Re:Zig, parser combinators, and why they're awesome by fulafel on Thursday March 11, 2021 @12:12AM (#26420523)
Zig is much easier to learn and simpler and has much of the safety when compared to the Rust-C spectrum. It also seems to be fun to write for lots of people. The metaprogramming system is also first rate and easy to understand.
Re:Zig, parser combinators, and why they're awesome by diragon on Thursday March 11, 2021 @01:56AM (#26421111)
It's pretty dreamy for us who wanted Rust to become "better C" but instead it became "better C++". Granted, that's what it was trying to become from the get-go, I just got confused and hopeful.
Re:Zig, parser combinators, and why they're awesome by 1_player on Thursday March 11, 2021 @06:32AM (#26422894)
Rust is to C++ what Zig hopes to be to C.

I don't mean "hope" disparagingly. We're just a few releases away to reach that point, IMO.

Go is what Thompson & Ritchie might have developed in an alternate universe had they used Limbo and Plan 9 before designing the C language.

Re:Zig, parser combinators, and why they're awesome by qaq on Thursday March 11, 2021 @02:19AM (#26421243)
well so far Zig looks to be one of the very few lang that got the async/sync two color functions sorted out.
Re:Zig, parser combinators, and why they're awesome by janjones on Thursday March 11, 2021 @02:25AM (#26421269)
It is also interestingly solved in Unison language (using "algebraic effects"), although it's just an early alpha version.

See https://jaredforsyth.com/posts/whats-cool-about-unison/

Re:Zig, parser combinators, and why they're awesome by gameswithgo on Wednesday March 10, 2021 @07:31PM (#26418570)
As a rough high level overview:

Rust is what you might imagine if starting over from scratch with C++, with a big emphasis on memory and type safety.

Zig is more like starting over from scratch with C, with a moderate emphasis on safety (no garbage collection or borrow checker, but undefined behavior handled more sanely than C)

Re:Zig, parser combinators, and why they're awesome by k__ on Wednesday March 10, 2021 @07:58PM (#26418767)
I had the impression Rust was more compatible with C than C++.
Re:Zig, parser combinators, and why they're awesome by pcwalton on Wednesday March 10, 2021 @09:49PM (#26419608)
Well, every language is more compatible with C than C++, because C is a subset of C++†. Even C++ is more compatible with C than with C++ compiled with a different compiler :)

† I know it's not a subset, but near enough for our purposes.