Labelled Blocks
const std = @import("std");
const expect = std.testing.expect;
test "block as an expression" {
// `break :label value` yields a value from the labelled block, so a
// multi-step computation can still produce a single const.
const count = blk: {
var sum: u32 = 0;
for (0..10) |i| sum += i;
break :blk sum;
};
try expect(count == 45);
try expect(@TypeOf(count) == u32);
}
test "labels also name scopes for shadowing" {
const outer_value: u32 = 1;
const result = blk: {
const outer_value_inner: u32 = 2;
break :blk outer_value + outer_value_inner;
};
try expect(result == 3);
}Label a block and break out of it with a value:
const count = blk: {
var sum: u32 = 0;
for (0..10) |i| sum += i;
break :blk sum;
};
The name blk is arbitrary. What matters is that a multi-statement computation
still produces a single const, so the intermediate var cannot leak into the
surrounding scope or be accidentally reused later.
This is the Zig answer to “I need a few lines to compute this, but I want the result to be immutable”, a pattern that otherwise pushes people toward a mutable variable with a wider scope than it deserves, or a single-use function.