Reflection
Reflection is the ability of a program to inspect and modify its own structure. Comptime lets us do compile-time reflection.
Let’s try to write a function that prints a struct in a more readable
format than the standard print function. It’ll reflect
on the type it’s given to get the struct fields.
const std = @import("std");
const print = std.debug.print;
const Color = struct {
red: u8,
green: u8,
blue: u8,
};
pub fn main() void {
const c: Color = .{
.red = 255,
.green = 0,
.blue = 255,
};
printStruct("color", c);
printStruct("my tuple", .{ 123, 4.56 });
}
// 'anytype' means the function will be specialized for
// different types.
fn printStruct(name: []const u8, v: anytype) void {
const T = @TypeOf(v);
print("{s}:\n", .{name});
const type_info = @typeInfo(T);
switch (type_info) {
// We have to write @"struct" here because
// 'struct' is a keyword.
.@"struct" => |s| {
const fields = s.fields;
// We need 'inline for' because 'fields' is
// only available at compile time.
inline for (fields) |f|
print(" {s}: {}\n", .{
f.name,
// @field gets a field by name.
@field(v, f.name),
});
},
// @compileError raises an error during
// compilation.
else => @compileError("expected struct"),
}
}$ zig run reflection.zig
color:
red: 255
green: 0
blue: 255
my tuple:
0: 123
1: 4.56
Next example: Build System.