Would it be possible for builtins like @mod
to be able to derive the limits of the integer type that is being cast into, similar to how the compiler understands bitshifting types must be log(T).
For example when i do this:
const whole: i32 = getBlackBoxNumber()
const remainder = @mod(whole, 8)
We know that remainder can only be a value between 0-7, and so it could easily be stored in a u8. Right now the compiler uses the same type as whole
. Meaning we get an i32 instead.
Obviously this would only work with comptime known values, but it could be a cool help/check, and I think is inline with decisions like bitshifting.
2 Likes
Compared to bitshift operators @mod also works with floating point numbers so it would be strange for it to work with one type but not with the other
1 Like
Huh. I never used modulus operator with a floating point number. I’ve always thought about it in the context of integer division.
There’s renewed interest in issue #3806, which would add ranged integer types to Zig.
When (if but hopefully when) that lands, constraining the result of @mod
to a range is simple if the modulus is comptime-known:
const remainder: @Int(0, 16) = @mod(some_val, 17);
That’s using the convention I consider proper, where a range is expressed inclusive of both values, so [start, end]
not [start, end)
as we do for e.g. slicing (but not for switch prongs).
Expressing the range of a modulus operation is actually a case for using the [start, end)
convention, but it’s the only one IMHO. Which would you rather work with:
const WeekDay: type = @Int(1, 7);
// or...
const WeekDay: type = @Int(1, 8);
It’s really only when a range is anchored at zero that expressing it exclusive of its highest value is convenient, and the whole point of ranged integers is to get away from that requirement.
1 Like
Y’know what? I changed my mind, modulus is an excellent argument for using inclusive ranges.
Consider (this is math not Zig):
[0, n-1] = a % n where n ∈ ℕ
[0, -1]
is not a valid range (it can be used as a notation for a range-of-nothing but that’s technically math abuse), and a % 0
is also invalid. So the equation doesn’t hold for 0
since the left term is impossible.
The alternative (math again):
[0, n) = a % n where n > 0
As it happens [0, 0)
is the not-math-abuse way of representing an empty range, and this is one of the reasons why as programmers we like semi-open intervals. But that’s why we have to specify that n
is positive: a % 0
is an impossibility that isn’t equal to the empty interval.
It makes sense for Zig to treat an integer type with a range including no integers as a type error, and dividing or @mod
by 0 is illegal behavior. So this is in fact an argument for closed interval / inclusive ranges.
2 Likes