blocks
Blocks are used to limit the scope of variable declarations:
test.zig
test "access variable after block scope" {
{
var x: i32 = 1;
}
x += 1;
}
$ zig test test.zig
./docgen_tmp/test.zig:5:5: error: use of undeclared identifier 'x'
x += 1;
^
Blocks are expressions. When labeled, break
can be used to return a value from the block:
test.zig
const std = @import("std");
const expect = std.testing.expect;
test "labeled break from labeled block expression" {
var y: i32 = 123;
const x = blk: {
y += 1;
break :blk y;
};
expect(x == 124);
expect(y == 124);
}
$ zig test test.zig
1/1 test "labeled break from labeled block expression"... OK
All 1 tests passed.
Here, blk
can be any name.
See also:
Shadowing
It is never allowed for an identifier to “hide” another one by using the same name:
test.zig
const pi = 3.14;
test "inside test block" {
// Let's even go inside another block
{
var pi: i32 = 1234;
}
}
$ zig test test.zig
./docgen_tmp/test.zig:6:9: error: redefinition of 'pi'
var pi: i32 = 1234;
^
./docgen_tmp/test.zig:1:1: note: previous definition is here
const pi = 3.14;
^
Because of this, when you read Zig code you can rely on an identifier always meaning the same thing, within the scope it is defined. Note that you can, however use the same name if the scopes are separate:
test.zig
test "separate scopes" {
{
const pi = 3.14;
}
{
var pi: bool = true;
}
}
$ zig test test.zig
1/1 test "separate scopes"... OK
All 1 tests passed.