🎓 A1Learner
🔍
0 of 55 lessons completed

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?