const std = @import("std");
pub fn main() void {
// loop 1
{
var i: usize = 0;
while (i < 3) : (i += 1) blk: {
std.debug.print("{}\n", .{i});
break :blk;
} else {
std.debug.print("end\n", .{});
}
}
// loop 2
{
var i: usize = 0;
blk: while (i < 3) : (i += 1) {
std.debug.print("{}\n", .{i});
continue :blk;
} else {
std.debug.print("end\n", .{});
}
}
}
I see why:
- the break version has the blk inside the while, label the expression that is the body of the loop, so a break there in side the loop machinery
- the continue version labels the entire while expression, and does the exact same thing: I would expect continue to be implemented that way, actually
So it makes sense, just the syntax makes it quite unobvious, and is very surprising.
Curious looking code but expected behavior. The break
leves a labeled block and has no interaction with the loop itself. The continue
actually does continue the loop and has nothing to do with the block containing it, which has no label. So this is possible in Zig given that both loops and blocks can have labels and break
works with both labeled loops and blocks.
considering you can return from a label with a value, I thought it would be an expression and guessed it would parse like this:
while(cond) expr // notice no braces
not
while(cond) { statement_list }
I believe you’re right. The thing is that in the first case, you have an expression in the form of a labeled block with curly braces that looks like a loop body but is just a single expression; and that expression evaluates to void
, which is also the case for the else
body and both bodies in the second loop. Basically this is to say that a loop body with braces is the same as a labeled block that evaluates to void
(returns (or break
s) nothing.)