zig
zig copied to clipboard
should the `orelse` operator be right-associative?
Consider the following code:
pub fn main() void {
const a: ?bool = false;
const b: ?bool = null;
_ = a orelse b orelse @panic("oh, no");
}
As of zig 0.11.0-dev.2298+5d63d1115
, this fails to compile with the following error message:
example.zig:4:20: error: expected optional type, found 'bool'
_ = a orelse b orelse @panic("oh, no");
^~~~~~~~~~~~~~~~~~~~~~~
This error message indicates that the line is being parsed in a left-associative fashion, i.e.
_ = (a orelse b) orelse @compileError("should not reach this");
In my opinion, the more intuitive behavior would be for orelse
to be right-associative, i.e.
_ = a orelse (b orelse @compileError("should not reach this"));
If this wasn't an explicit design choice, I think it makes sense to change it. Right-associativity would make orelse
behave like a short-circuiting boolean operator, which I think is logical behavior given its naming and functionality. For directly applicable prior-art, both C#'s and Swift's null-coalescing operators are right-associative.
Note: possible interaction with the accepted proposal at https://github.com/ziglang/zig/issues/114#issuecomment-302235077 in which associativity is a factor (and which was written before orelse
existed).
I don't get how associativity plays into this...
if (a orelse b) orelse @panic()
here a
is nonnull, b
is never evaluated. The left hand side is nonnull so the panic isn't evaluated either.
if a orelse (b orelse @panic())
a
is again nonnull and the right hand side is never evaluated.
This looks more like a compiler bug to me.
orelse
isnt eager in its evaluation atm even for consts. that's why a orelse unreachable
and a.?
have different behavior for comptime-known optionals.