have not played with zig for a while, remain in the C world.

with the cleanup attribute(a cheap "defer" for C), and the sanitizers, static analysis tools, memory tagging extension(MTE) for memory safety at hardware level, etc, and a zig 1.0 still probably years away, what's the strong selling point that I need spend time with zig these days? Asking because I'm unsure if I should re-try it.

My 2ct: A much more useful stdlib (that's also currently the most unstable part though, and I don't agree with all the design decisions in the stdlib - but mostly still better than a nearly useless stdlib like C provides - and don't even get me started about the C++ stdlib heh), integrated build system and package manager (even great for pure C/C++ projects), and comptime with all the things it enables (like straightforward reflection and generics).

It also fixes a shitton of tiny design warts that we've become accustomed to in C (also very slowly happening in the C standard, but that will take decades while Zig has those fixes now).

Also, probably the best integration with C code you can get outside of C++. E.g. hybrid C/Zig projects is a regular use case and has close to no friction.

C won't go away for me, but tinkering with Zig is just more fun :)

I really like Zig as a language, but I think the standard library is a huge weakness. I find the design extremely inconsistent. It feels like a collection of small packages, not a coherent unit. And I personally think this std.Io interface is on a similar path. The idea of abstracting our all I/O calls is great, but the actual interface is sketchy, in my opinion.

Could you expand on what are the design decisions you disapprove of ? You got me curious

Many parts of the stdlib don't separate between public interface and internal implementation details. It's possible to accidentially mess with data items which are clearly meant to be implementation-private.

I think this is because many parts of the stdlib are too object-oriented, for instance the containers are more or less C++ style objects, but this style of programming really needs RAII and restricted visibility rules like public/private (now Zig shouldn't get those, but IMHO the stdlib shouldn't pretend that those language features exist).

As a sister comment says, Zig is a great programming language, but the stdlib needs some sort of basic and consistent design philosophy whitch matches the language capabilities.

Tbf though, C gets around this problem by simply not providing a useful stdlib and delegating all the tricky design questions to library authors ;)

Honestly getting to mess with internal implementation details is my favorite part of using Zig's standard library. I'm working on a multithreaded interpreter right now, where each object has a unique index, so I need effectively a 4GB array to store them all. It's generally considered rude to allocate that all at once, so I'm using 4GB of virtual memory. I can literally just swap out std.MultiArrayList's backing array with vmem, set its capacity, and use all of its features, except now with virtual memory[1].

[1] https://github.com/smj-edison/zicl/blob/bacb08153305d5ba97fc...

I would at least like to see some sort of naming convention for implementation-private properties, maybe like:

    const Bla = struct {
        // public access intended
        bla: i32,
        blub: i32,
        // here be dragons
        _private: struct {
            x: i32,
            y: i32,
        },
    };
...that way you can still access and mess up those 'private' items, but at least it's clear now which of the struct items are part of the 'public API contract' and which are considered internal implementation details which may change on a whim.

This is my main frustration with the push back against visibility modifiers. It's treated as an all or nothing approach, that any support for visibility modifiers locks anyone out from touching those fields.

It could just be a compiler error/warning that has to be explicitly opted into to touch those fields. This allows you to say "I know this is normally a footgun to modify these fields, and I might be violating an invariant condition, but I am know what I'm doing".

"Visibility" invariably bites you in the ass at some point. See: Rust, newtypes and the Orphan rule, for example.

As such, I'm happy to not have visibility modifiers at all.

I do absolutely agree that "std" needs a good design pass to make it consistent--groveling in ".len" fields instead of ".len()" functions is definitely a bad idea. However, the nice part about Zig is that replacement doesn't need extra compiler support. Anyone can do that pass and everyone can then import and use it.

> This allows you to say "I know this is normally a footgun to modify these fields, and I might be violating an invariant condition, but I am know what I'm doing".

Welcome to "Zig will not have warnings." That's why it's all or nothing.

It's the single thing that absolutely grinds my gears about Zig. However, it's also probably the single thing that can be relaxed at a later date and not completely change the language. Consequently, I'm willing to put up with it given the rest of the goodness I get.

Tbf, C++/C# style public/private/protected is definitely too restricted in many situations, and other more flexible approaches are pretty much still research territory.

They could do something like OCaml modules and signatures but more permissive. Module author writes the public signature and that's what the type checker runs against, but if you want, you can "downcast" the module to the actual signature, revealing implementation details.

Aah, that's a good point. I suppose you could argue that the doc notes indicate whether something it meant to be accessed directly, like when ArrayList mentions "This field is intended to be accessed directly.", but that's really hard to determine at a glance.

How do you cope with the lack of vector operators? I am basically only writing vector code all day and night, and the lack of infix operators for vectors is just as unacceptable as not having them for normal ints and floats would be.

Nobody is asking for Pizza * Weather && (Lizard + Sleep), that strawman argument to justify ints and floats as the only algebraic types is infuriating :(

I'd love to read a blog post about your Zig setup and workflow BTW.

I'm coming from C so I got used to writing code like this ;)

    fn computeVsParams(rx: f32, ry: f32) shd.VsParams {
        const rxm = mat4.rotate(rx, .{ .x = 1.0, .y = 0.0, .z = 0.0 });
        const rym = mat4.rotate(ry, .{ .x = 0.0, .y = 1.0, .z = 0.0 });
        const model = mat4.mul(rxm, rym);
        const aspect = sapp.widthf() / sapp.heightf();
        const proj = mat4.persp(60.0, aspect, 0.01, 10.0);
        return shd.VsParams{ .mvp = mat4.mul(mat4.mul(proj, state.view), model) };
    }
Zig also has a `@Vector` type for SIMD-style vector math though, but I haven't been using that because sometimes I want to add methods to the vector types.

What I would like to see though is a Ziggified version of the Clang extended vector and matrix extensions.

If you want to write really cursed code, you could use comptime to implement a function that takes comptime strings and parses them into vector function calls ;)

I've actually thought about that, and looked a little into canonical/idiomatic ways to implement a DSL in Zig, and didn't find anything small and natural.

I just find it intellectually offensive that this extremely short-sighted line is drawn after ints and floats, any other algebraic/number types aren't similarly dignified.

If people had to write add(2, mul(3, 4)) etc for ints and floats the language would be used by exactly nobody! But just because particular language designers aren't using complex numbers and vectors all day, they interpret the request as wanting stupid abstract Monkey + Banana * Time or whatever. I really wish more Language People appreciated that there's only really one way to do complex numbers, it's worth doing right once and giving proper operators, too. Sure, use dot(a, b) and cross(a, b) etc, that's fine.

The word "number" is literally half of "complex number", and it's not like there are 1024 ways to implement 2D, 3D, 4D vector and complex number addition, subtraction, multiplication, maybe even division. There are many languages one can look to for guidance here, e.g. OpenCL[0] and Odin[1].

[0] OpenCL Quick Reference Card, masterpiece IMO: https://www.khronos.org/files/opencl-1-2-quick-reference-car...

[1] Odin language, specifically the operators: https://odin-lang.org/docs/overview/#operators

I don't think any language that's not well-established, let alone one that isn't stabilised yet, would have a strong selling point if what you're looking for right now is to write production code that you'll maintain for a decade or more to come (I mean, companies do use languages that aren't as established as C in production apps, including Zig, but that's certainly not for everyone).

But if you're open to learning languages for tinkering/education purposes, I would say that Zig has several significant "intrinsic" advantages compared to C.

* It's much more expressive (it's at least as expressive as C++), while still being a very simple language (you can learn it fully in a few days).

* Its cross-compilation tooling is something of a marvel.

* It offers not only spatial memory safety, but protection from other kinds of undefined behaviour, in the form of things like tagged unions.