Idiomatic counting loop over u32?

What’s the idiomatic way to loop 0 to n using u32 as an index type?

It seems that Zig 0.11 unconditionally picks usize for index type

const std = @import("std");
const assert = std.debug.assert;

pub fn main() void {
    const lo: u32 = 0;
    const hi: u32 = 10;
    for (lo..hi) |i| {
        assert(@TypeOf(i) == usize);
    }
}

What’s better,

A)

    var i = lo;
    while (i < hi) : (i += 1) {
    }

or B)

    for (lo..hi) |i_usize| {
        const i: u32 = @intCast(i_usize);
    }
2 Likes

I go for A) in this case, and opt for B) only if I need the for loop index as well, ie:

for (lo..hi, idx_lo..idx_hi) |i_usize, idx_usize| {...}

Generally, while loop is for counting iterations, while for loop is for iterating over slices of things.

2 Likes

Ya know… I think part of the reason this is less obvious than it should be is that we don’t have loop-scoped variables for while loops. I’d go a bit further and actually say that:

{ // addiontal outer scope
    var i = lo;
    while (i < hi) : (i += 1) {
    }
}

Is more “idiomatically” a counting loop because we’re preventing i from leaking into the outer world. In my mind, this reads as “the variable i exists for the sole purpose of this loop”.

Loop initialized variables is one thing I wish we had. I’ve thought about some theoretical syntax for this, but that’s a different topic :slight_smile:

5 Likes

This is my dream (syntactic) feature too.

2 Likes