Bits monstrosity

const mask: u8 = @intCast(@as(u8, 1) << @intCast(bit));

Do we really have to write stuff this way? instead of:

const mask: u8 = 1 << bit;

This works, and prints 16:

const std = @import("std");

pub fn main() void {
    const bit: u8 = 4;
    const mask: u8 = 1 << bit;
    std.debug.print("{d}\n", .{mask});
}

What is the type of bit in your case?

2 Likes

It was more of a general question ragarding numbercrunching.
Also when using for() loops casting is needed,.

const width: u32;
for(0..width) |i|
{
    // and now the `i` has magically become a usize
}

I guess it is party inexperience. But still it sometimes makes code less readable.

Related.
I am curious as to what made Andrew reject this.

Well I guess because there are other issues. First the bugs than maybe some language additions.
Looping should definitely be possible with all int types, also negative ones.
Maybe even with inclusive numbers (using ...).

This is a duplicate of the issue @LucasSantos91 mentioned (and it is also closed):

However Andrew mentions in the linked comment above:

there is a chance you may get your wish with #3806.

Which is this issue:

where @mnemnion linked to that comment.

So if we get integer types which can be any range, we might get for loops with arbitrary types too.

I think that would be pretty cool, but those integer types of any range might be a lot of work to implement, so I think we need to have some patience for that.

2 Likes

Yes I saw some of the links. Except the last one.
I think you are right it will be quite some work to get these things right.

(edit) like these things, which in C# creates a neverending loop as I noted by personal accident.

byte b = 10;
while (b >= 0)
{
        b--;
}

In short: yes. Zig peer type coercion has a very simple rule for numeric types:

Integers coerce to integer types which can represent every value of the old type, and likewise Floats coerce to float types which can represent every value of the old type.

Shifting has an additional rule: the shiftand must be of a width log₂ of the shifted type, so to shift a u64 the shiftand must be a u6 or smaller. A consequence of this rule is that a comptime_int can’t just be cast to the result type.

These rules can be annoying, but they solve more problems than they cause. I often add this function to code:

pub fn cast(N: type, val: anytype) N {
     return @intCast(val);
}

So I can write cast(u8, something) instead of @as(u8, @intCast(something)), this makes the resulting code easier to read and understand.

3 Likes