30 comments

[ 2.0 ms ] story [ 62.9 ms ] thread
Picked up zig a few days ago - similar experience.

The build system and c-interop is amazing, targeting any arch/os from such a small toolchain makes me never want to use makefiles or even cmake again. The language itself definitely has a learning curve tho. Found myself fighting the syntax and needing some common things like sscanf often.

Btw kristoff's 4 part tutorial was really useful to integrate c libs: https://zig.news/kristoff/compile-a-c-c-project-with-zig-368...

The integrated toolchain/build system and C/C++ compiler + easy interop is clearly well designed, valuable and practical.

The only grips I have, so far, are some syntax idiosyncrasies.

I am also afraid that their metaprogramming system will not turn out to be as a net positive. It is undeniably powerful (like all systems of this type are) and better designed than previous attempts, and yet this lead to issues about readability/debuggability and inflated compilation time.

The old adage, less is more, is something that should be taken into account with programming language design.

> The old adage, less is more, is something that should be taken into account with programming language design.

This is a case of less is more, in a way.

Instead of having to learn an entirely different, half-baked language to do metaprogramming (C defines/macros), you just have Zig.

The only problem is that even though this approach leads to less additional added syntax for similar tasks, Zig unlocks potential for metaprogramming that goes far beyond C macros. And like with C macros, this could be abused. It's up to the user not to take it too far.

But yes, there's issues with debugability. I hope Zig improves that

I hope one day Zig is capable of targeting AVR microcontrollers, all anyone seems to target with new languages for embedded these days is ARM. Great, exactly what we need, another homogeneity in CPU architectures.
Zig is not perfect on targeting AVR, but it's capable enough to not be a PITA.

Since we've made microzig supporting AVR targets (currently atmega328p only, feel free to add more), i'm not using anything else.

Oh and: We can target an ATtiny1616 without problems. avr-libc doesn't officially support the Tiny2 family yet.

328p is what I was thinking of when writing this!
Then you definitly should check out MicroZig!

I will push my bugfixes for current master branch tomorrow or later, so you can directly play around!

> all anyone seems to target with new languages for embedded these days is ARM

.. and RISC-V. Zig does work with RISC-V, to some degree at least.

I hope Zig support for AVR improves. For legacy reasons. But I don't think we need more AVR going forward. It's rather proprietary, no?

If everything goes according to plan, Zig will be the only language that is capable of actually utilizing the AVR 24 bit address space properly, while also allowing you to make nice optimizations with the smaller 16 bit address spaces (Zig has first class address spaces on memory)

Also, RISC-V support is working quite fine, and i don't see much problems with that.

> But I don't think we need more AVR going forward. It's rather proprietary, no?

AVR is Arduino. It would be a bad action to basically say: "well, zig is not going to support the most widespread maker hardware on the market"

Zig doesn't support AVR? It's news to me since I was using Zig on Atemega328p a whole year ago and even with true debugging via debugwire in VSCode.
Zig will have a C back-end which will provide support for many of this kind of hardware. And I think you can make avr work at present but I do not know the state of the support.
I can't wait for Zig to reach a stable point. It has a lot of cool features but right now it (rightfully so at this stage) moves so fast it's nearly impossible to keep up with unless your interest in using Zig is "keeping up with Zig's early development". Not just from a syntax/feature perspective but from a "oh that compiler bug was fixed in commit xyz" or "oh that language feature doesn't actually compile correctly right now if the data is evenly divisible by 4 when run on a little endian target on a Wednesday". Alright maybe not that obscure but you get the idea :).
Can you give an example of a compiler bug you've run into? I feel like they are very rare for most use cases, these days.
I've got a thing for packed structs (network encodings tend to be zealous to use weird bit widths and packings to save a byte on the header) but unfortunately for me they seem to be one of the most troublesome things in the language and every time I return to try them out it seems like there is always more to fix - though I usually get farther and farther in each round. The self-hosted compiler seems to have calmed things with it but there is a flow of mis-compilations still and they tend to hang around for a couple of releases each. For a good read of how weird these can be here is a bug report from last month https://github.com/ziglang/zig/issues/13480
yeah, that makes sense. packed structs are the place where I had trouble in the past.
While you are right about it not being stable, and about packed struct being a bit wonky, I've been using Zig a lot for some hobby projects and rarely run into problems. APIs are in flux of course, but that usually only takes minutes to fix as long as you keep the compiler reasonably up to date. Maybe there's a fix required every month or so, but it seems that most things are settling down. YMMV, I mostly use the basic stuff and sprinkle some comptime here and there.
> packed struct being a bit wonky

That's putting it a bit mildly from what I recall the last time I used them. They work on LE if you don't color too far outside the lines, but otherwise I would describe their state as "almost completely broken".

Field ordering being endian dependent, while historically how things are done with bitfields, seems questionable to me anyways.

I don’t know zig, but I’d like to know if the syntax idiosyncrasies are warranted, or are they are designed just to be different from other languages? IMO using well established syntax makes life easy for a lot of new folks who want to learn this language.
For any design decision, there is always a cost/benefit tradeoff.

In this case, I think the design team might be underestimating the cost of those idiosyncrasies, simply because they've been working with them for so long.

It is hard to keep a fresh eye on a product of any kind when you've spent years looking at it, designer blindness is not something that should be ignored.

From my interactions with the Zig dev team, I don't think that's an accurate assessment. They spend a long time thinking and talking about the tradeoffs of doing things the way they are doing them vs more traditional routes and, in my opinion, they usually make a solid well reasoned decision based on Zig core principles.
I agree, they explain almost every big design decision and the process seems to be mostly rational and thorough.

But still, it does not really account for their own blindness.

In practice we can rationalize almost everything.

I read feedback, but I can't do anything with a general phrase like "syntax idiosyncrasies". I need concrete examples to understand the problem.
First of all thanks for Zig. I like your work. As I said, I don't know Zig. I read the OP's article and saw these: std.debug.print("{s}\n", .{arg}); vs std.debug.print("{s}\n", arg); // This is intuitive coming from other langs. and std.debug.print("I just want some output\n", .{}); // Not at all expected .{}

There might be good reasons why they are designed like that, but we outsiders find that syntax idiosyncratic.