Zig Unions
A union is a type that can hold a value of one of several types, but only one at a time. A tagged union also records which type it currently holds.
Read a number payload
This union holds a number payload. The switch captures it and prints it.
const std = @import("std");
const Value = union(enum) { number: i32, word: []const u8 };
pub fn main() !void {
const out = std.io.getStdOut().writer();
const v = Value{ .number = 42 };
switch (v) {
.number => |n| try out.print("{d}\n", .{n}),
.word => |w| try out.print("{s}\n", .{w}),
}
}
Read a word payload
The same union type can instead hold a word. The switch runs the word branch this time.
const std = @import("std");
const Value = union(enum) { number: i32, word: []const u8 };
pub fn main() !void {
const out = std.io.getStdOut().writer();
const v = Value{ .word = "zig" };
switch (v) {
.number => |n| try out.print("{d}\n", .{n}),
.word => |w| try out.print("{s}\n", .{w}),
}
}
Pick a label for the active member
A switch can turn each member into a label. The two values below pick different labels.
const std = @import("std");
const Value = union(enum) { number: i32, word: []const u8 };
pub fn main() !void {
const out = std.io.getStdOut().writer();
const a = Value{ .number = 1 };
const b = Value{ .word = "hi" };
const first = switch (a) {
.number => "number",
.word => "word",
};
const second = switch (b) {
.number => "number",
.word => "word",
};
try out.print("{s} {s}\n", .{ first, second });
}
Example
const std = @import("std");
const Shape = union(enum) { circle: i32, square: i32 };
fn measure(s: Shape) i32 {
return switch (s) {
.circle => |r| r * 2,
.square => |side| side * side,
};
}
pub fn main() !void {
const out = std.io.getStdOut().writer();
try out.print("{d}\n", .{measure(Shape{ .circle = 3 })});
try out.print("{d}\n", .{measure(Shape{ .square = 4 })});
}
Key points
- Union: A union holds one value chosen from several listed types.
- Tagged: union(enum) stores a tag, which is a label naming the active member.
- Payload: A member such as word: []const u8 carries a value called its payload.
- Create: Value{ .number = 42 } makes a union holding the number 42.
- Switch: A switch on a tagged union runs the branch for the active member.
- Capture: A branch written .number => |n| gives that branch the payload as n.
In this example, measure switches on the active member of the Shape union. A circle with radius 3 gives a diameter of 6, and a square with side 4 gives an area of 16.
Note
In Zig, only the active member of a union holds a usable value.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
In switch (v) { .number => |n| ..., a union holding .number = 42 gives n which value?