# If you had one wish for zig, what would it be?

**URL:** <https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069>\
**Category:** Brainstorming\
**Tags:** language, community\
**Created:** [April 20, 2026, 4:18pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069 "2026-04-20T16:18:52Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![spiffyk](https://ziggit.dev/user_avatar/ziggit.dev/spiffyk/32/7202_2.png) [@spiffyk](https://ziggit.dev/u/spiffyk)\
**Post date:** [April 21, 2026, 10:34am UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/41 "2026-04-21T10:34:42Z")

</div>

Btw, not that it matters much, but this

> [@pierrelgol](#):
>
> ```zig
> var data: [1024]u32 = undefined;
> @memset(&data, 1);
> 
> ```

could be written like this:

```zig
const data: [1024]u32 = @splat(1);

```

* * *

Otherwise, I like this idea! 🙂

---

<div class="post-metadata">

**Author:** ![Cloudef](https://ziggit.dev/user_avatar/ziggit.dev/cloudef/32/1370_2.png) [@Cloudef](https://ziggit.dev/u/Cloudef)\
**Post date:** [April 21, 2026, 10:44am UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/42 "2026-04-21T10:44:26Z")

</div>

When doing `@splat` for large arrays, I always encourage to look at the disassembly so that you aren’t accidentally bloating your binary.

This is bit poor example, but showcases what can happen:  
[https://zig.godbolt.org/z/dr6GEqaEG](https://zig.godbolt.org/z/dr6GEqaEG)

For temporary arrays or const arrays, splat often gets optimized away.

---

<div class="post-metadata">

**Author:** ![codegasm](https://ziggit.dev/user_avatar/ziggit.dev/codegasm/32/3035_2.png) [@codegasm](https://ziggit.dev/u/codegasm)\
**Post date:** [April 21, 2026, 10:46am UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/43 "2026-04-21T10:46:42Z")

</div>

The ability to see the zig code equivelant to what comptime operations generate.

---

<div class="post-metadata">

**Author:** ![pierrelgol](https://ziggit.dev/user_avatar/ziggit.dev/pierrelgol/32/10233_2.png) [@pierrelgol](https://ziggit.dev/u/pierrelgol)\
**Post date:** [April 21, 2026, 10:55am UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/44 "2026-04-21T10:55:05Z")

</div>

Yeah I know completely forgot ahah, but yeah I think some form of syntax support for basically automatic windowing, could be very handy

---

<div class="post-metadata">

**Author:** ![spiffyk](https://ziggit.dev/user_avatar/ziggit.dev/spiffyk/32/7202_2.png) [@spiffyk](https://ziggit.dev/u/spiffyk)\
**Post date:** [April 21, 2026, 11:29am UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/45 "2026-04-21T11:29:31Z")

</div>

Huh, I would have expected that to generate the exact same assembly! Looks like a bug to me. Good to know in any case!

Alright, I’ve got my wish (after having hanged around in this thread for some time without making one): _I wish for this to be fixed_ 😁

---

<div class="post-metadata">

**Author:** ![floooh](https://ziggit.dev/user_avatar/ziggit.dev/floooh/32/2989_2.png) [@floooh](https://ziggit.dev/u/floooh)\
**Post date:** [April 21, 2026, 1:23pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/46 "2026-04-21T13:23:55Z")

</div>

…about C vs Zig designated init…

> What’s missing in zig for that? (I admit I did not look at the standard, but zig already does many struct init that C does).

The main feature I’m missing is more flexible array initialization (direct indexing and allowing incomplete array initialization which would need to be filled up with the declaration-defaults).

The next thing which is often coming in very handy is chained designators (e.g. `x.y.y = 123`).

E.g. have a look at this C code:

```c
    state.pip = sg_make_pipeline(&(sg_pipeline_desc){
        .layout = {
            .attrs = {
                [ATTR_texcube_pos].format = SG_VERTEXFORMAT_FLOAT3,
                [ATTR_texcube_color0].format = SG_VERTEXFORMAT_UBYTE4N,
                [ATTR_texcube_texcoord0].format = SG_VERTEXFORMAT_SHORT2N
            }
        },
        .shader = shd,
        .index_type = SG_INDEXTYPE_UINT16,
        .cull_mode = SG_CULLMODE_BACK,
        .depth = {
            .compare = SG_COMPAREFUNC_LESS_EQUAL,
            .write_enabled = true
        },
        .label = "texcube-pipeline"
    });

```

…the `attrs` initialization has all the missing features:

- it’s an array of 16 items, but only 3 are initialized
- the array indices are coming from (code-generated) constants (e.g. those are generated by a shader-compiler tool) - this eliminates one source of errors where the shader code might not match the CPU-side code, the vertex attribute indices might not be in order and they may have gaps, but this is irrelevant for the above code, it will “just work”
- the attr-array init uses chained designators (`[ATTR_texcube_pos].format = SG_VERTEXFORMAT_FLOAT3`)

The current workaround in Zig is to use an init-block, but I feel like this is a really awkward hack for such simple situations. Init-blocks should only be required when the initialization actually requires complex initialization logic.

E.g. this is the same code in Zig (but this is only okay-ish because the attrs array is wrapped in another public struct):

```ts
    state.pip = sg.makePipeline(.{
        .shader = sg.makeShader(shd.texcubeShaderDesc(sg.queryBackend())),
        .layout = init: {
            var l = sg.VertexLayoutState{};
            l.attrs[shd.ATTR_texcube_pos].format = .FLOAT3;
            l.attrs[shd.ATTR_texcube_color0].format = .UBYTE4N;
            l.attrs[shd.ATTR_texcube_texcoord0].format = .SHORT2N;
            break :init l;
        },
        .index_type = .UINT16,
        .depth = .{
            .compare = .LESS_EQUAL,
            .write_enabled = true,
        },
        .cull_mode = .BACK,
    });

```

To be fair to Zig, only very few languages come close to C99 designated-init.

- Rust is a joke (way too verbose and redundant), but at least it has proper “init blocks” (because blocks are expressions in Rust): [sokol-rust/examples/texcube/texcube.rs at eb316158c916ee8e24c9860cedde3f4469a0f614 · floooh/sokol-rust · GitHub](https://github.com/floooh/sokol-rust/blob/eb316158c916ee8e24c9860cedde3f4469a0f614/examples/texcube/texcube.rs#L128-L150)
- Jai is also surprisingly bad (don’t know if this has improved in the meantime): [sokol-jai/examples/cube-sapp/module.jai at 09af92dd283e9f1b4c25b3e6848556e41538c966 · colinbellino/sokol-jai · GitHub](https://github.com/colinbellino/sokol-jai/blob/09af92dd283e9f1b4c25b3e6848556e41538c966/examples/cube-sapp/module.jai#L83-L99) - although looking at the code I think it’s just poorly copied from another language example…
- Odin is pretty good: [sokol-odin/examples/texcube/main.odin at 5c6289bce5003f1695fd74efc092daea7b2187f9 · floooh/sokol-odin · GitHub](https://github.com/floooh/sokol-odin/blob/5c6289bce5003f1695fd74efc092daea7b2187f9/examples/texcube/main.odin#L117-L132)
- D is a weird mix of ‘pretty good’ and ‘absolutely terrible’: [sokol-d/examples/texcube/source/texcube.d at 14399a06b9c75cfdd00eac0ce649512955d0dfac · floooh/sokol-d · GitHub](https://github.com/floooh/sokol-d/blob/14399a06b9c75cfdd00eac0ce649512955d0dfac/examples/texcube/source/texcube.d#L107-L139)
- C3 pretty much copies C (kinda expected): [sokol-c3/examples/texcube/main.c3 at daa183df8bf13875702b76bf26d9d58325b5038b · floooh/sokol-c3 · GitHub](https://github.com/floooh/sokol-c3/blob/daa183df8bf13875702b76bf26d9d58325b5038b/examples/texcube/main.c3#L111-L126)

---

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [April 21, 2026, 1:39pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/47 "2026-04-21T13:39:00Z")

</div>

> [@IntegratedQuantum](#):
>
> For me it would also be for loop counting variable types, including the ability to do this:
> 
> ```zig
> for (0..32) |i: u5| {} // max value does not have to fit the type
> 
> ```

How about this?

```zig
for (@IntRange(0,31)) |i| {} // Ranges should be closed intervals, fight me

```

That’s just a type, so `for (u8)` would give you `[0,255]`. Meaning you could write this particular one `for (u5)`, but options like `for (@IntRange(0xc0, 0xff))` would exist as well.

I don’t think the original `0..n+1` syntax should narrow to an `@IntRange` though. Tempting as it is from a correctness standpoint, I bet ranged integers will be different enough to work with that there will be times when “make it unsigned and make it Large” is what’s wanted.

---

<div class="post-metadata">

**Author:** ![gyre](https://ziggit.dev/user_avatar/ziggit.dev/gyre/32/8002_2.png) [@gyre](https://ziggit.dev/u/gyre)\
**Post date:** [April 21, 2026, 1:49pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/48 "2026-04-21T13:49:01Z")

</div>

Working (draft) spec, so that we know what’s **formally** a Zig program.

I know a spec will a lot of constraint to the evolution of the language, but the constraint could also be a restraining factor to adding the “next shiny new thing in town” to the language.

It’ll also enable others to start writing alternative implementation of Zig.

---

<div class="post-metadata">

**Author:** ![invlpg](https://ziggit.dev/letter_avatar_proxy/v4/letter/i/13edae/32.png) [@invlpg](https://ziggit.dev/u/invlpg)\
**Post date:** [April 21, 2026, 2:29pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/49 "2026-04-21T14:29:02Z")

</div>

> [@mnemnion](#):
>
> ```zig
> for (@IntRange(0,31)) |i| {} // Ranges should be closed intervals, fight me
> 
> ```

But if they’re half-open you get nice properties:

```zig
@IntRange(a, b).len == b - a
// and therefore
@IntRange(0, n).len == 0

// adjacent intervals look contiguous:
@IntRange(a, b) ++ @IntRange(b, c) == @IntRange(a, c)

// No need to special case the empty interval
@IntRange(0, 0)

// How would you even right that for a closed interval?
@ClosedIntRange(0, -1)

// Or for unsigned?
@ClosedIntRange(@as(u32, 0), @as(u32, -1)) // uh oh, looks like we're doing 2^32 iterations

```

[Related essay by Dijkstra on why numbering should start at zero.](https://www.cs.utexas.edu/~EWD/transcriptions/EWD08xx/EWD831.html)

---

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [April 21, 2026, 2:37pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/50 "2026-04-21T14:37:39Z")

</div>

You’re treating these as though they are values, but they’re types.

At least consider that I might have read Dijkstra once or twice, quite possibly before you were born. I have considered and rejected all of those arguments a long, long time ago, as did the Ada authors when they actually implemented ranged integers.

I’ll save my ammo for some other time, however. Doesn’t seem like the place for it.

But you might figure it out on your own! So I encourage you to ask: “if someone who already knew all that in his bones, and takes it for granted, still thinks ranged integer types should be closed intervals: why might that be?”

Related question: why does Zig use closed ranges in switch statements?

---

<div class="post-metadata">

**Author:** ![invlpg](https://ziggit.dev/letter_avatar_proxy/v4/letter/i/13edae/32.png) [@invlpg](https://ziggit.dev/u/invlpg)\
**Post date:** [April 21, 2026, 2:40pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/51 "2026-04-21T14:40:45Z")

</div>

I’m not engaging with that level of condescension.

---

<div class="post-metadata">

**Author:** ![darnellbrawner](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/bcef8e/32.png) [@darnellbrawner](https://ziggit.dev/u/darnellbrawner)\
**Post date:** [April 21, 2026, 4:17pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/52 "2026-04-21T16:17:26Z")

</div>

It would be nice if the Matrix stuff saw some love I did a small building a neural network course that was python based and I just the equivalent with zig. It just seems like every time I start using multiple dimensional arrays it feels clumsy in zig. I think this will go away with continued video game optimizations stuff.

The ability to extend existing functionality. Like instead of creating a wrapper for an std struct and adding your 2 custom methods you could just extend the existing flow. Like std.ArrayList.mycustom\_methond.

---

<div class="post-metadata">

**Author:** ![ScottRedig](https://ziggit.dev/user_avatar/ziggit.dev/scottredig/32/5880_2.png) [@ScottRedig](https://ziggit.dev/u/ScottRedig)\
**Post date:** [April 21, 2026, 6:08pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/53 "2026-04-21T18:08:40Z")

</div>

This is already effectively possible, though not with the syntax you’re proposing:

```zig
const std = @import("std");

const E = enum {
    foo,
    bar,

    fn T(e: E) type {
        return switch (e) {
            .foo => []const u8,
            .bar => [32]u8,
        };
    }
};

fn useUnionThingy(comptime e: E, u: e.T()) void {
    switch (e) {
        .foo => std.debug.print("Hello {s}!\n", .{u}),
        .bar => @compileError("Sema doesn't hit this"),
    }
}

pub fn main() void {
    const e: E = .foo;
    const u: e.T() = "Ziggit";

    useUnionThingy(e, u);
}

```

If you’re also using the union type without a comptime known field, you could define E and U with either:

- `const U = union(enum) {...}` and `const E = @typeInfo(U).@"union".tag_type.?`
- `const E = enum {...}` and `const U = union(E) {...}`

Then use `@FieldType(U, @tagName(e))`.  
There’s lots of subtle variations on this that depend on exactly what you’re trying to do, but I think this gives the overall idea.

---

<div class="post-metadata">

**Author:** ![darnellbrawner](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/bcef8e/32.png) [@darnellbrawner](https://ziggit.dev/u/darnellbrawner)\
**Post date:** [April 21, 2026, 6:37pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/54 "2026-04-21T18:37:09Z")

</div>

> [@Best way to extend std](https://ziggit.dev/t/best-way-to-extend-std/14101/3):
>
> A nice thing about Zig is that option 1 is always a possibility since containers can’t have private fields, so you can access the entire local state of any container even if you’re not inside of its namespace.

The last reply gave a nice code example.

---

<div class="post-metadata">

**Author:** ![chung-leong](https://ziggit.dev/user_avatar/ziggit.dev/chung-leong/32/999_2.png) [@chung-leong](https://ziggit.dev/u/chung-leong)\
**Post date:** [April 21, 2026, 9:01pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/55 "2026-04-21T21:01:35Z")

</div>

At some point, I think the language should add built-in support for garbage-collected strings ala Delphi. Given the importance of language to human existence, having a specialized type is well justified in my opinion. Since strings do not contain pointers, we’re looking at a fairly simple reference counting system.

---

<div class="post-metadata">

**Author:** ![marler8997](https://ziggit.dev/user_avatar/ziggit.dev/marler8997/32/77_2.png) [@marler8997](https://ziggit.dev/u/marler8997)\
**Post date:** [April 21, 2026, 9:07pm UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/56 "2026-04-21T21:07:06Z")

</div>

A testament to Andrew and the core team, I’m having a hard time coming up with something. I could not say the same if we were talking about other languages.

I think my wish would then be, to magically get the state of the git repository from the future when zig hits 1.0. And don’t try to trick me genie, that also includes the bootstrap binaries commited to source control. I’d be quite disappointed to have the code without the ability to compile it.

---

<div class="post-metadata">

**Author:** ![pierrelgol](https://ziggit.dev/user_avatar/ziggit.dev/pierrelgol/32/10233_2.png) [@pierrelgol](https://ziggit.dev/u/pierrelgol)\
**Post date:** [April 22, 2026, 12:04am UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/57 "2026-04-22T00:04:16Z")

</div>

True I had to think long and honestly at this point it feels more like asking for my money back when I already have the sandwich

---

<div class="post-metadata">

**Author:** ![ww520](https://ziggit.dev/letter_avatar_proxy/v4/letter/w/c2a13f/32.png) [@ww520](https://ziggit.dev/u/ww520)\
**Post date:** [April 22, 2026, 12:36am UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/58 "2026-04-22T00:36:16Z")

</div>

Most features in Zig are good. I’m productive with the language. One ergonomic improvement would be adding support for returning value from a multiple statement block. E.g.

```zig
const x = if (condition) {
    s1;
    s2;
    break_with s3;
} else {
    s1;
    s2;
    or_last_statement_as_the_value_of_the_block
}

```

Same with `orelse`, `catch`, and `switch`.

I really don’t like the current work-around of using label. I always have to look up the label syntax and their placement. It just breaks the flow of programming.

---

<div class="post-metadata">

**Author:** ![WiserOrb](https://ziggit.dev/user_avatar/ziggit.dev/wiserorb/32/3853_2.png) [@WiserOrb](https://ziggit.dev/u/WiserOrb)\
**Post date:** [April 22, 2026, 2:30am UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/59 "2026-04-22T02:30:03Z")

</div>

Yeah. That’s the pattern I’ve started using myself. The only slightly annoying thing is that the tag and the object are now two separate things that I have to “carry around” in the code  
To be fair it is not a huge problem.

---

<div class="post-metadata">

**Author:** ![WiserOrb](https://ziggit.dev/user_avatar/ziggit.dev/wiserorb/32/3853_2.png) [@WiserOrb](https://ziggit.dev/u/WiserOrb)\
**Post date:** [April 22, 2026, 2:34am UTC](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069/60 "2026-04-22T02:34:00Z")

</div>

Ah yes another thing I would love is a @noAlias built-in.

It accepts a pointer `a` and returns another pointer `b`.

The semantics are that every load and store through `b` are isolated from the rest, and the modification get visible to the rest of the pointers only when `b` falls out of scope.

The usage would be:

```zig
const row1 = @noAlias(matrix.row(1));
const row2 = @noAlias(matrix.row(2));

const row3 = @noAlias(matrix.row(3));
for (row1, row2, &row3) |v1, v2, *v3| {
    // Here the optimizer should have all the information that it needs
    v3.* = v1 + v2;
} 

```

[Previous page](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069.md?page=2)

[Next page](https://ziggit.dev/t/if-you-had-one-wish-for-zig-what-would-it-be/15069.md?page=4)
