# For-loop counter other than usize

**URL:** <https://ziggit.dev/t/for-loop-counter-other-than-usize/4744>\
**Category:** Help\
**Tags:** language\
**Created:** [June 16, 2024, 2:49am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744 "2024-06-16T02:49:05Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![smallkirby](https://ziggit.dev/user_avatar/ziggit.dev/smallkirby/32/2291_2.png) [@smallkirby](https://ziggit.dev/u/smallkirby)\
**Post date:** [June 16, 2024, 2:49am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/1 "2024-06-16T02:49:05Z")

</div>

Hello.

As far as I know, the loop counter of for-loop using a range syntax is always `usize`:

```zig
for (0..10) |i| {} // `i` is `usize`

```

However, it is really annoying to downcast the counter to pass it to functions that take other types such as `u32`.

Is there any easy ways to make the counter other types?

---

<div class="post-metadata">

**Author:** ![dimdin](https://ziggit.dev/user_avatar/ziggit.dev/dimdin/32/1457_2.png) [@dimdin](https://ziggit.dev/u/dimdin)\
**Post date:** [June 16, 2024, 3:47am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/2 "2024-06-16T03:47:53Z")

</div>

Hello @smallkirby

There is no way to declare the range type.  
See why: [Why are range variables always usize? - #2 by IntegratedQuantum](https://ziggit.dev/t/why-are-range-variables-always-usize/3026/2)

There are two ways to loop: `for` and `while`.

- Cast to the desired type:

- Declare the desired type:

EDIT: added `@intCast`

---

<div class="post-metadata">

**Author:** ![endlessly\_amused](https://ziggit.dev/user_avatar/ziggit.dev/endlessly_amused/32/2551_2.png) [@endlessly\_amused](https://ziggit.dev/u/endlessly_amused)\
**Post date:** [June 16, 2024, 3:52am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/3 "2024-06-16T03:52:26Z")

</div>

I came up with something similar

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

pub fn main() !void {

{
    var counter:u8=10;
    while (counter!=0) : (counter-=1) {
        std.debug.print("All your coding are belong to us in {d}; Which happens to be a {}\n", .{counter,@TypeOf(counter) });
    } // end of while
}

{
    const counter=[_]u8{1,2,3,4,5,6,7,8,9};
    for (counter) |item|{
        std.debug.print("All your coding are belong to us in {d}; Which happens to be a {}\n", .{item,@TypeOf(item) });
    }
}

{
    for (0..10) |index|{
        const index2:u8=@intCast(index);
        std.debug.print("All your coding are belong to us in {d}; Which happens to be a {}\n", .{index2,@TypeOf(index2) });
    }
}

}

```

---

<div class="post-metadata">

**Author:** ![endlessly\_amused](https://ziggit.dev/user_avatar/ziggit.dev/endlessly_amused/32/2551_2.png) [@endlessly\_amused](https://ziggit.dev/u/endlessly_amused)\
**Post date:** [June 16, 2024, 4:08am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/4 "2024-06-16T04:08:28Z")

</div>

Hi

> [@dimdin](#):
>
> ```zig
> for (0..10) |_i| {
> const i = @as(u32, _i);
> }
> 
> ```

This didn’t work for me I got

```zig
main_test.zig:7:28: error: expected type 'u32', found 'usize'
        const i = @as(u32, _i);
                           ^~
main_test.zig:7:28: note: unsigned 32-bit int cannot represent all possible unsigned 64-bit values

```

Perhaps I mistyped it? Here is the full code.

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

pub fn main() !void {

{
    for (0..10) |_i| {
        const i = @as(u32, _i);
        std.debug.print("All your coding are belong to us in {d}; Which happens to be a {}\n", .{i,@TypeOf(i) });
    }
}

}

```

Anyway I got round this issue with

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

pub fn main() !void {

//{
// for (0..10) |_i| {
// const i = @as(u32, _i);
// std.debug.print("All your coding are belong to us in {d}; Which happens to be a {}\n", .{i,@TypeOf(i) });
// }
//}

{
for (0..10) |_i| {
  const i = @as(u32, @truncate(_i) );
  std.debug.print("All your coding are belong to us in {d}; Which happens to be a {}\n", .{i,@TypeOf(i) });
}
}

}

```

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [June 16, 2024, 4:15am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/5 "2024-06-16T04:15:20Z")

</div>

I think what you’re looking for (in general) is `@intCast`: [Documentation - The Zig Programming Language](https://ziglang.org/documentation/master/#intCast)

Truncation is best used when you really intend to truncate… I can imagine that you may end up with weird results if you’re not careful with truncation.

---

<div class="post-metadata">

**Author:** ![endlessly\_amused](https://ziggit.dev/user_avatar/ziggit.dev/endlessly_amused/32/2551_2.png) [@endlessly\_amused](https://ziggit.dev/u/endlessly_amused)\
**Post date:** [June 16, 2024, 4:23am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/6 "2024-06-16T04:23:13Z")

</div>

I can see I was being evil. In my defense I was only trying to get the code working.  
My MO is to get it compiled and working, then clean up the mess afterwards.

My first post example did as you suggested.

```zig
{
    for (0..10) |index|{
        const index2:u8=@intCast(index);
        std.debug.print("All your coding are belong to us in {d}; Which happens to be a {}\n", .{index2,@TypeOf(index2) });
    }
}

```

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [June 16, 2024, 4:25am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/7 "2024-06-16T04:25:12Z")

</div>

> [@endlessly\_amused](#):
>
> In my defense I was only trying to get the code working.

It’s easy to forget all the casting rules/operators. s’all good `¯\_(ツ)_/¯`

---

<div class="post-metadata">

**Author:** ![smallkirby](https://ziggit.dev/user_avatar/ziggit.dev/smallkirby/32/2291_2.png) [@smallkirby](https://ziggit.dev/u/smallkirby)\
**Post date:** [June 16, 2024, 4:54am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/8 "2024-06-16T04:54:05Z")

</div>

Thanks everyone.  
I understood that there’s no way to allow non-`usize` counter for a loop counter. So I’m going to use a downcast (truncate) or while loop instead. Thank you for your advices 🙂

---

<div class="post-metadata">

**Author:** ![endlessly\_amused](https://ziggit.dev/user_avatar/ziggit.dev/endlessly_amused/32/2551_2.png) [@endlessly\_amused](https://ziggit.dev/u/endlessly_amused)\
**Post date:** [June 16, 2024, 5:02am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/9 "2024-06-16T05:02:14Z")

</div>

Give me a little bit longer almost got a solution for which you might be happy with and isn’t evil.  
Just got to put the guard rails in and write the tests.

---

<div class="post-metadata">

**Author:** ![endlessly\_amused](https://ziggit.dev/user_avatar/ziggit.dev/endlessly_amused/32/2551_2.png) [@endlessly\_amused](https://ziggit.dev/u/endlessly_amused)\
**Post date:** [June 16, 2024, 5:37am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/10 "2024-06-16T05:37:01Z")

</div>

Here is what I came up with … It’s a bit clunky. I am sure I can refine it.  
Please feel free to comment and improve.

It accepts u8,u16 or u32

## Example

In the below example it counts to 0..3 in u8 using comptime.

```zig
    for ( countTo(@as(u8,3)) ) |item| {}

```

## Output

```zig
zig run main_ziggit.zig
(Evil laugh) All your coding are belong to us in 0; Which happens to be a u8
(Evil laugh) All your coding are belong to us in 1; Which happens to be a u8
(Evil laugh) All your coding are belong to us in 2; Which happens to be a u8
sgeorge@debian:~/zig_bits/play/20240616_ziggig_forloop/src$ zig test main_ziggit.zig
All 1 tests passed.

```

## Full code

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

pub fn main() void {

    // To use this; change u8 to your desired type ie u8,u16,u32. Then 10 your desired count up to maybe 3
    // this works in comptime, so the I don't think the long arrays should be a problem
    for ( countTo(@as(u8,3)) ) |item| {
        std.debug.print("(Evil laugh) All your coding are belong to us in {d}; Which happens to be a {}\n", .{item,@TypeOf(item) });
    } // end of for

// // Lets do some quick tests
// for ( countTo(@as(u16,3)) ) |item| {
// std.debug.print("(Evil laugh) All your coding are belong to us in {d}; Which happens to be a {}\n", .{item,@TypeOf(item) });
// } // end of for
//
//
// for ( countTo(@as(u32,3)) ) |item| {
// std.debug.print("(Evil laugh) All your coding are belong to us in {d}; Which happens to be a {}\n", .{item,@TypeOf(item) });
// } // end of for
//

} // end of main

pub fn countTo(comptime top:anytype) [top]@TypeOf(top)
{
    comptime std.debug.assert(@TypeOf(top) == u8 or @TypeOf(top) == u16 or @TypeOf(top) == u32);
    var return_array:[top]@TypeOf(top)=undefined;
    for (0..top) |item| { return_array[item]=@intCast(item); }
    return return_array;
} // end of fn

test "countTo"
{
    try std.testing.expect( countTo(@as(u8,3))[0] == 0);
    try std.testing.expect( countTo(@as(u8,3))[1] == 1);
    try std.testing.expect( countTo(@as(u8,3))[2] == 2);

    try std.testing.expect( countTo(@as(u16,3))[0] == 0);
    try std.testing.expect( countTo(@as(u16,3))[1] == 1);
    try std.testing.expect( countTo(@as(u16,3))[2] == 2);

    try std.testing.expect( countTo(@as(u32,3))[0] == 0);
    try std.testing.expect( countTo(@as(u32,3))[1] == 1);
    try std.testing.expect( countTo(@as(u32,3))[2] == 2);

}

```

---

<div class="post-metadata">

**Author:** ![smallkirby](https://ziggit.dev/user_avatar/ziggit.dev/smallkirby/32/2291_2.png) [@smallkirby](https://ziggit.dev/u/smallkirby)\
**Post date:** [June 16, 2024, 7:52am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/11 "2024-06-16T07:52:04Z")

</div>

Hi, @endlessly_amused .  
I really appreciate your answer, but I feel that typing `countTo(@as(u8, 3))` is not so much simpler or easier than:

```zig
for (0..3) |_i| {
    const i: u8 = @truncate(_i);
} 

```

---

<div class="post-metadata">

**Author:** ![endlessly\_amused](https://ziggit.dev/user_avatar/ziggit.dev/endlessly_amused/32/2551_2.png) [@endlessly\_amused](https://ziggit.dev/u/endlessly_amused)\
**Post date:** [June 16, 2024, 8:10am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/12 "2024-06-16T08:10:51Z")

</div>

> [@smallkirby](#):
>
> I really appreciate your answer, but I feel that typing `countTo(@as(u8, 3))` is not so much simpler or easier than:
> 
> ```zig
> for (0..3) |_i| {
> const i: u8 = @truncate(_i);
> } 
> 
> ```

Go with what you feel comfortable with. And thanks for the feed back.

However, having said that, it was mentioned that @truncate was probably not a good idea.  
It just chops off the leading zeros. You should probably use @intCast() instead.

There were two versions.

My version was

```zig
    for (0..3) |_index|{
        const index:u8=@intCast(_index);
        std.debug.print("Count {d}; in {}\n", .{index,@TypeOf(index) });
    }

```

The winning entry and therefore better entry (from dimdin) was

```zig
for (0..10) |_i| {
  const i = @as(u32, @intCast(_i));
}

```

All the best

---

<div class="post-metadata">

**Author:** ![endlessly\_amused](https://ziggit.dev/user_avatar/ziggit.dev/endlessly_amused/32/2551_2.png) [@endlessly\_amused](https://ziggit.dev/u/endlessly_amused)\
**Post date:** [June 17, 2024, 6:18am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/13 "2024-06-17T06:18:46Z")

</div>

For anyone who is interested, here is my final piece of code to answer the question.

Q) A For-loop, with a range syntax of (0..3), will use a usize type. Can we make it u23?

A) This code will count to 3 in u23, using comptime.

```zig
    const top:u23=3; 
    for (@"0.."(top)) |item| {
        std.debug.print("1 Count {d}; in {}\n", .{item,@TypeOf(item) });
    }

```

## Full code

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

pub fn main() !void {

    const top:u23=3; // will count 0..3 all in u23
    for (@"0.."(top)) |item| {
        std.debug.print("1 Count {d}; in {}\n", .{item,@TypeOf(item) });
    }

}

pub fn @"0.."(comptime top:anytype) [top]@TypeOf(top)
{
    switch (@typeInfo(@TypeOf(top))) {
        .Int,.ComptimeInt => {
            comptime std.debug.assert(top >= 1);
            var return_array:[top]@TypeOf(top)=undefined;
            for (0..top) |item| { return_array[item]=@intCast(item); }
            return return_array;
        },
       else => {
            std.debug.print("!! You need to supply an int to @\"0..\"()\n", .{} );
            unreachable;
       },
    }
}

```

---

<div class="post-metadata">

**Author:** ![FObersteiner](https://ziggit.dev/user_avatar/ziggit.dev/fobersteiner/32/1177_2.png) [@FObersteiner](https://ziggit.dev/u/FObersteiner)\
**Post date:** [June 17, 2024, 6:43am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/14 "2024-06-17T06:43:00Z")

</div>

while it’s cool that you can do such stuff in Zig, …I would still go with the `while` loop ^^

btw. this question was (one of the rare zig questions) on StackOverflow recently; [Zig for loop range iterator with custom int type - Stack Overflow](https://stackoverflow.com/q/78609420/10197418)

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [June 17, 2024, 6:47am UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/15 "2024-06-17T06:47:23Z")

</div>

This is clever, but please carefully consider the cost of doing this.

This can cause calls to memset and increases the workload. This is also particularly rough if you try to count to anything large as it can also consume a lot of stack memory.

Make sure to always look at the results of the assembly when doing something like this because it may not be doing what you think it is.

---

<div class="post-metadata">

**Author:** ![dude\_the\_builder](https://ziggit.dev/user_avatar/ziggit.dev/dude_the_builder/32/557_2.png) [@dude\_the\_builder](https://ziggit.dev/u/dude_the_builder)\
**Post date:** [June 17, 2024, 1:02pm UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/16 "2024-06-17T13:02:20Z")

</div>

> [@Range: a simple little numeric range iterator](https://ziggit.dev/t/range-a-simple-little-numeric-range-iterator/4772):
>
> With one additional line of code, you get: Control the type of iterated numeric values. var r = Range(i8){ .from = -2, .to = 2 }; while (r.next()) |i| { ... Ascending or descending iteration. var r = Range(i8){ .from = 2, .to = -2 }; while (r.next()) |i| { ... Control the iteration step. var r = Range(i8){ .from = -2, .to = 2, .step = 2 }; while (r.next()) |i| { ... Range over the values of a type. var r = Range(u4){ .inclusive = true }; while (r.next()) |i| { ... [https://codeberg.o…](https://codeberg.org/dude_the_builder/range)

---

<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:** [June 17, 2024, 5:57pm UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/17 "2024-06-17T17:57:40Z")

</div>

I’d like it if the language supported something like this:

```zig
for (0..) |byte: u8| {
    // ....
}

```

There are a few possible ways to phrase this, two more: `for(@as(u8, 0..))`, `for(@as(u8, 0)..)`, I just chose my favorite from the [associated proposal](https://github.com/ziglang/zig/issues/14704). The other two turn `@as` into “magic”, which, a builtin _can_ be magic, but that tendency should be resisted. The above syntax is consistent with specifying the type of a numeric literal to cast it down from `comptime_int`.

That issue was closed, this was the main part of the reasoning given (quote is Andrew Kelley):

> If you tried to implement your proposal, you would see the problems with it.

That strikes me as a good reason for Andrew / the Zig Foundation to not work on the issue, but not so great a reason to close it. There’s a difference between “this is not good for Zig” and “this is harder than you think, and the benefits are not worth the time I would have to devote to it”. Either of these is a fully legitimate reason for the core team not to devote time to the feature, but if the latter reasoning is in fact primary, maybe someone else would be willing to tackle the implementation complexity without making it the team’s problem.

There’s also a question of where to stop, but “for ranges are increment only, integer only, and always increment by one, automatically” is defensible. Anything else should be using a `while` loop, whether with a postcondition or an iterator. That keeps the semantics of `for` loops clean, and consistent with their use to iterate over slices/arrays/Vectors, but also opens up range types which aren’t `usize`, which is clearly valuable (or people wouldn’t keep asking this question).

It seems to have been closed as part of a general cleanup (see the rest of the comment). That kind of thing happens. I do hope room is left to reconsider the question at some later time.

---

<div class="post-metadata">

**Author:** ![castholm](https://ziggit.dev/user_avatar/ziggit.dev/castholm/32/1330_2.png) [@castholm](https://ziggit.dev/u/castholm)\
**Post date:** [June 18, 2024, 4:36pm UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/18 "2024-06-18T16:36:32Z")

</div>

I’d like to offer a slightly different perspective: You should use the right tool for the right job.

My understanding is that the `for` loop is intended for forward-iterating over array elements, which are indexed by `usize`, one element at a time. It is not intended for general “count from N to M” tasks. Prior to the addition of multi-object `for` loops in Zig 0.11.0 you couldn’t even iterate over ranges, only an array and optionally its indices (equivalent to what is now `for (slice, 0..) |a, i|`).

Refer back to the “communicate intent precisely” bulletpoint of `zig zen`. If your `for` loop iterates over a range like `0..10` and you are not using the range variable for indexed access, you are likely misusing the `for` loop construct and should consider instead using the general-purpose `while` loop for clarity, to avoid giving a reader the false impression that you are iterating over the elements of some array.

---

<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:** [June 18, 2024, 5:09pm UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/19 "2024-06-18T17:09:19Z")

</div>

> [@castholm](#):
>
> `for` loop is intended for forward-iterating over array elements, which are indexed by `usize`,

This is working backward from what is, to what should be.

Also, peer type resolution takes care of indexing by smaller values:

```zig
test "index with a u8" {
    const nums = [_]u64{ 23, 34, 56, 78 };
    const idx: u8 = 1;
    std.debug.print("index with u8: {d}\n", .{nums[idx]});
}

```

As it should.

> [@castholm](#):
>
> It is not intended for general “count from N to M” tasks.

Debatable:

```zig
test "count from N to M" {
    const n = 5;
    const m = 10;
    for (n..m) |i| {
        std.debug.print("index is {d}\n", .{i});
    }
}

```

Sure looks to me like you can use it for, checking my notes here, “general count from N to M tasks”.

> [@castholm](#):
>
> you are likely misusing the `for` loop construct

Says you!

---

<div class="post-metadata">

**Author:** ![gonzo](https://ziggit.dev/user_avatar/ziggit.dev/gonzo/32/54_2.png) [@gonzo](https://ziggit.dev/u/gonzo)\
**Post date:** [June 18, 2024, 6:01pm UTC](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744/20 "2024-06-18T18:01:36Z")

</div>

I have seen this argument before. In my mind, it would apply to an hypothetical `foreach` within zig: the name would make it extremely clear you are iterating over each and every element (of an array).

I liked @dude_the_builder’s `Range` construction – if only that could be used with a `for` loop… One can only dream.

[Next page](https://ziggit.dev/t/for-loop-counter-other-than-usize/4744.md?page=2)
