This commit is contained in:
2026-01-19 05:43:29 +09:00
parent 40f41a4fd0
commit 0f6fddd794
36 changed files with 1724 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
const expect = @import("std").testing.expect;
// Payload captures use the syntax `|value|` and appear in many places, some of which we've seen already.
// Wherever they appear, they are used to "capture" the value from something.
// With if statements and optionals.
test "optional-if" {
const maybe_num: ?usize = 10;
if (maybe_num) |n| {
try expect(@TypeOf(n) == usize);
try expect(n == 10);
} else {
unreachable;
}
}
// With if statements and error unions. The else with the error capture is required here.
test "error union if" {
const ent_num: error{UnknownEntity}!u32 = 5;
if (ent_num) |entity| {
try expect(@TypeOf(entity) == u32);
try expect(entity == 5);
} else |err| {
_ = err catch {};
unreachable;
}
}
// With while loops and optionals. This may have an else block.
test "while optional" {
const sequence = [_]?u8{ 0xFF, 0xCC, 0x00, null };
var i: usize = 0;
while (sequence[i]) |num| : (i += 1) {
try expect(@TypeOf(num) == u8);
}
try expect(i == 3);
try expect(sequence[i] == null);
}
// With while loops and error unions. The else with the error capture is required here.
var numbers_left2: u32 = undefined;
fn eventuallyErrorSequence() !u32 {
return if (numbers_left2 == 0) error.ReachedZero else blk: {
numbers_left2 -= 1;
break :blk numbers_left2;
};
}
test "while error union capture" {
var sum: u32 = 0;
numbers_left2 = 3;
while (eventuallyErrorSequence()) |value| {
sum += value;
} else |err| {
try expect(err == error.ReachedZero);
}
}
// For loops.
test "for capture" {
const x = [_]i8{ 1, 5, 120, -5 };
for (x) |v| try expect(@TypeOf(v) == i8);
}
// Switch cases on tagged unions.
const Info = union(enum) {
a: u32,
b: []const u8,
c,
d: u32,
};
test "switch capture" {
const b = Info{ .a = 10 };
const x = switch (b) {
.b => |str| blk: {
try expect(@TypeOf(str) == []const u8);
break :blk 1;
},
.c => 2,
//if these are of the same type, they
//may be inside the same capture group
.a, .d => |num| blk: {
try expect(@TypeOf(num) == u32);
break :blk num * 2;
},
};
try expect(x == 20);
}
// As we saw in the Union and Optional sections above,
// values captured with the `|val|` syntax are immutable (similar to function arguments),
// but we can use pointer capture to modify the original values.
// This captures the values as pointers that are themselves still immutable,
// but because the value is now a pointer, we can modify the original value by dereferencing it:
const eql = @import("std").mem.eql;
test "for with pointer capture" {
var data = [_]u8{ 1, 2, 3 };
for (&data) |*byte| byte.* += 1;
try expect(eql(u8, &data, &[_]u8{ 2, 3, 4 }));
}