logoalt Hacker News

Four Months of Zig

118 points • by ibobev • yesterday at 8:13 PM • 71 comments • view on HN

Comments

i2talics • yesterday at 11:01 PM

Why does everyone love being able to control the allocator in Zig? I rarely want this low level control over the allocator, I would rather have an easy to use interface to malloc/free (such as RAII) or would prefer the language push me to avoiding allocations when unnecessary. C and Zig users are always talking about how arena allocators are easier to use than the alternative but I disagree because the alternative is extremely easy to use when the language makes it so.

Arenas have a lot of footguns like growing out of control if you don't have space in your logic to delete them (e.g. suppose every new HTTP connection required obtaining a new allocation from the primary arena -- now you have a memory leak). They also aren't necessarily faster than malloc: I remember hearing a case where mimalloc was faster than an arena for a one-shot program like a linker because reclaiming space improved cache locality. Plus it's difficult to implement things like growable vectors or hashmaps using an arena without wasting space.

I just don't see how "futz about with the allocator constantly" and "use an arena" is actually a good default.

➕ show 4 replies
philippta • today at 7:24 AM

On the Odin vs Zig allocator bit:

In Zig you pass an allocator to every function that allocates, even if it doesn't make a lot of sense.

    const arr = std.ArrayList(i64).empty;
    arr.append(allocator, 1);
    arr.append(allocator, 2);
    arr.append(allocator, 3);
This rarely makes sense, as it's not really useful to append using a different allocator than you used previously.

In Odin, allocators are passed in the init, stored as part of the struct and reused in the append.

    arr := make([dynamic]i64, 0, 10, context.allocator)
    append(&arr, 1)
    append(&arr, 2)
    append(&arr, 3)
➕ show 3 replies
delifue • today at 2:24 AM

The article says some Zig advantages but it's worth noting that all these advantages are tradeoffs.

Zig makes handling error easy but makes retaining error information hard. The result is that Zig developers either write more code than other languages to store diagnostic information, or just simply discard diagnostic information. The second makes it much harder to debug because the useful error information is discarded.

About the TigerStyle, it's worth noting that TigerBeetle doesn't even support variable-sized string type. You can store fixed-sized data, such as a string that's at most 32 bytes. What if the order information contains string longer than 32 bytes? Then you need to store that string in antoher database. TigerBeetle is not a general database. Static memory allocation doesn't fit most applicaitons.

The fallable allocation is useful in embedded system and OS development etc., but useless in common application programming, because OOM results in crash rather than failed allocaiton.

➕ show 1 reply
22c • yesterday at 11:14 PM

First I'm hearing of TigerStyle.

> The time to solve performance, and get the 1000x wins, is in the design phase, when you can't profile.

How does this make practical sense? I find it immensely easier to fix performance issues by profiling, benchmarking, finding hotspots. Things that weren't obviously performance bottlenecks during design become obvious when you profile.

Interesting write-up though. I haven't properly tried zig but I like reading these "initial impressions" style articles about it.

➕ show 2 replies
michidk • yesterday at 10:39 PM

Pretty nice! I wrote a similar piece two years ago: https://blog.lohr.dev/after-a-day-of-programming-in-zig Great to see things are moving in the right direction.

duoro • today at 3:49 AM

I want your honest opinion on Zig, for dev or internal tools I always use Rust. Probably not because its the best choice for that project, but simply because its more popular. Same reason everyone uses React instead of things like Solid or Svelte that I find much better than React. Is it the same case with Zig as well?

Atlas48 • yesterday at 10:36 PM

I can't wait until Zig is a little more stable, I'd love to get into it more because the metaprogramming seems like such a draw.

paaloeye • yesterday at 9:47 PM

Does ReTangled have anything to do with https://tangled.org?

➕ show 1 reply
alexboehm • yesterday at 11:16 PM

I agree with anyzig, it's amazing.

I made a PR to add a default zig, which was rejected, I've been using it ever since though.

https://github.com/marler8997/anyzig/pull/71

yje07039 • today at 3:07 AM

How much of the four months went to keeping up with breaking changes? Thats been my main blocker with zig, more than the language itself.

LoganDark • yesterday at 9:15 PM

> In Rust you can use ?, which is quicker than unwrap, but you also have to do something like Result<Type, Box<dyn std::error::Error>

No, you don't! When returning Result<T, E>, you can use ? on any Result<T2, E2> where E: From<E2>. In other words E doesn't have to be Box<dyn>, it just has to satisfy From<E2>.

Crates like thiserror make it easy to define your own error types that can be easily converted from all the other error types you can encounter in your functions! I do this whenever it doesn't make sense to use an inner error type directly, or whenever a function does its own validation that deserves its own error variant.

On top of that, I tend to also have error variants for each place in the function rather than only for each type of inner error. At error sites I do something like `.map_err(MyError::PlaceInTheFunction)?` rather than only `?`, and then errors become like a very efficient backtrace :)

➕ show 1 reply
llm_nerd • yesterday at 11:50 PM

Sort of related from yesterday - https://news.ycombinator.com/item?id=50247203

(about zig's reimplementation of the libc, and some rough edges)

paaloeye • yesterday at 8:49 PM

$curl: (6) Could not resolve host: gracefulliberty.com HN effect?

➕ show 1 reply
peter_d_sherman • today at 4:14 AM

>"The IO parameter is even more powerful, even if it is newer. It is well worth the breaking changes required to bring it about (even if I skipped the 0.15.0 -> 0.16.0 transition). In Zig, every function that interacts with the underlying operating system (with caveats) requires an "IO" parameter. This provides the context for input, output, and everything else.

Porting Zig to new operating systems is mostly just porting IO."

Nice!

(In Software Engineering, I think with this change, Zig nailed Separation Of Concerns: (https://en.wikipedia.org/wiki/Separation_of_concerns) aka modularity/modular design, at least with respect to handling the asymmetries of different OS's I/O APIs/syscalls - rather nicely!)

Anyway, very interesting article!

Related:

https://ziglang.org/download/0.16.0/release-notes.html#IO-as...

https://www.ziglang.in/learn/standard-library/io-interface/

ChubbyGlasses • today at 7:09 AM

[dead]