These overflow operators are SO erratic. You can do two_fifty *%4 but can't do two_fifty +%750. And why result is type u8 even when I change to "var result = zero + two - one * two / one / 3;"? 🤔
Zig will try to coerce numeric literals if it can without losing data, so in the case of two_fifty +% 750, two_fifty has an explicit type, so the operation will try to coerce 750 to that type (u8); this can't be done without losing data so an error occurs. If you declare a var with type u16 and value 750 and try the same operation with that, no error occurs because Zig can coerce the u8 to a u16 for the result type. This is called peer type resolution and you can read more about it here: ziglang.org/documentation/0.11.0/#Peer-Type-Resolution
@@dudethebuilder well... I understand the point. But just seems ineffective create an overflow operator that can be overflowed. Looks like bad design. Loving the vids btw. 🤩
I feel like you shouldn't be adding 750 to a u8 anyway. I guess it depends on the context but the way I see it, you should be working with equal types as much as possible. And you can always mod your number to make it fit into a u8 if you need to.
Great video! I am trying to follow along (having zig 0.12.0-dev.2811, as zig-0.11.0 would not work on my machine). Looking at type coercion now and trying this: // type coercion const byte: u8 = 200; const word: u16 = 999; var dword: u32 = byte * word; // doing multiplication here not addition as in the video dword += 1; // zig 0.12.xx does not allow unmutated variables so I add 1 to dword std.debug.print("dword: {} ", .{dword}); // should output 199801 Fails at compile time with this message: src\main.zig:40:24: error: overflow of integer type 'u16' with value '199800' var dword: u32 = byte * word; ~~~~~^~~~~~ dword, being an u32 obviously is large enough for 199800. What u16 variable is the compiler complaining about?
Good question! I believe this is due to the way "peer type resolution" works in Zig. This is the process whereby the compiler finds the minimum common type in an operation with two types that can be safely coerced by widening. In byte * word, you have a u8 * u16, so the compiler will resolve to u16 as the type of this operation. This happens before the compiler then would coerce the u16 to a u32 for the assignment operation. So the result of byte * word has to first fit in a u16 to then be widened to a u32. Maybe this is a place where a future improvement to the compiler could see this ultimate result type (u32) and allow the operation.
Oh i'm loving this so far! Seems like a pretty comfortable language
These overflow operators are SO erratic. You can do two_fifty *%4 but can't do two_fifty +%750. And why result is type u8 even when I change to "var result = zero + two - one * two / one / 3;"? 🤔
Zig will try to coerce numeric literals if it can without losing data, so in the case of two_fifty +% 750, two_fifty has an explicit type, so the operation will try to coerce 750 to that type (u8); this can't be done without losing data so an error occurs. If you declare a var with type u16 and value 750 and try the same operation with that, no error occurs because Zig can coerce the u8 to a u16 for the result type. This is called peer type resolution and you can read more about it here: ziglang.org/documentation/0.11.0/#Peer-Type-Resolution
@@dudethebuilder well... I understand the point. But just seems ineffective create an overflow operator that can be overflowed. Looks like bad design. Loving the vids btw. 🤩
I feel like you shouldn't be adding 750 to a u8 anyway. I guess it depends on the context but the way I see it, you should be working with equal types as much as possible. And you can always mod your number to make it fit into a u8 if you need to.
Great video!
I am trying to follow along (having zig 0.12.0-dev.2811, as zig-0.11.0 would not work on my machine).
Looking at type coercion now and trying this:
// type coercion
const byte: u8 = 200;
const word: u16 = 999;
var dword: u32 = byte * word; // doing multiplication here not addition as in the video
dword += 1; // zig 0.12.xx does not allow unmutated variables so I add 1 to dword
std.debug.print("dword: {}
", .{dword}); // should output 199801
Fails at compile time with this message:
src\main.zig:40:24: error: overflow of integer type 'u16' with value '199800'
var dword: u32 = byte * word;
~~~~~^~~~~~
dword, being an u32 obviously is large enough for 199800. What u16 variable is the compiler complaining about?
Good question! I believe this is due to the way "peer type resolution" works in Zig. This is the process whereby the compiler finds the minimum common type in an operation with two types that can be safely coerced by widening. In byte * word, you have a u8 * u16, so the compiler will resolve to u16 as the type of this operation. This happens before the compiler then would coerce the u16 to a u32 for the assignment operation. So the result of byte * word has to first fit in a u16 to then be widened to a u32. Maybe this is a place where a future improvement to the compiler could see this ultimate result type (u32) and allow the operation.