🎓 A1Learner
🔍
0 of 46 lessons completed

Zig Comptime Patterns

A comptime pattern is a reusable way of using compile-time information to generate code for many types. It turns one generic idea into specific behavior for each type it meets.

Printing every field

An inline loop over struct fields prints each field name and value, so one comptime pattern serves any struct with integer fields.

const std = @import("std");
pub fn main() !void {
    const out = std.io.getStdOut().writer();
    const Point = struct { x: i32, y: i32 };
    const p = Point{ .x = 3, .y = 4 };
    inline for (@typeInfo(Point).@"struct".fields) |f| {
        try out.print("{s}={d}\n", .{ f.name, @field(p, f.name) });
    }
}

Choosing by kind

A kind dispatch function returns one word for integers, another for floats, and a third word for other kinds.

fn kindName(comptime T: type) []const u8 {
    return switch (@typeInfo(T)) { .int => "integer", .float => "float", .bool => "boolean", else => "other" };
}
const std = @import("std");
pub fn main() !void {
    const out = std.io.getStdOut().writer();
    try out.print("{s}\n", .{kindName(i32)});
    try out.print("{s}\n", .{kindName(f64)});
    try out.print("{s}\n", .{kindName(bool)});
}

Listing enum choices

An inline loop over enum fields prints every choice name, so the list stays correct when choices change.

const std = @import("std");
pub fn main() !void {
    const out = std.io.getStdOut().writer();
    const Color = enum { red, green, blue };
    inline for (@typeInfo(Color).@"enum".fields) |f| {
        try out.print("{s}\n", .{f.name});
    }
}

Example

fn kindName(comptime T: type) []const u8 {
    return switch (@typeInfo(T)) { .int => "integer", .float => "float", .bool => "boolean", else => "other" };
}
const std = @import("std");
pub fn main() !void {
    const out = std.io.getStdOut().writer();
    const Sensor = struct { temp: i32, level: i32 };
    const s = Sensor{ .temp = 22, .level = 5 };
    try out.print("kind-i32={s}\n", .{kindName(i32)});
    try out.print("kind-f64={s}\n", .{kindName(f64)});
    inline for (@typeInfo(Sensor).@"struct".fields) |f| {
        try out.print("{s}={d}\n", .{ f.name, @field(s, f.name) });
    }
}

Key points

  • Comptime pattern: a comptime pattern is a reusable technique that uses compile-time information for many types.
  • Inline loop: an inline loop is a loop over compile-time items that runs once per item during compilation.
  • Field visit: a field visit is visiting one field of a struct during an inline loop.
  • Kind dispatch: kind dispatch is choosing a result from the kind of a type.
  • Type name: a type name is the text name of a type, such as i32.

The example combines two comptime patterns in one program. Kind dispatch names the kind of two types. Field visits then print every field of a sensor reading.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What does an inline loop over struct fields do?