Zig has the @field
builtin which allows you to access a struct
/union
/enum
member given a comptime string field name.
E.g., as given by the above link,
var p = Point{ .x = 0, .y = 0 };
@field(p, "x") = 4;
@field(p, "y") = @field(p, "x") + 1;
However, for my specific application, I need to be able to initialize a union(enum)
given a comptime []const u8
, and I would prefer not to do this with an if
-else if
-tree to prevent verbosity.
I imagine something much like JavaScript's ["<field-name>"]
member accessing but with static instead of dynamic strings:
const c = MonochromaticColor{ ["r"] = 255 }; // "MonochromaticColor" is a contrived enum
One can emulate the fanciful structure initialization
const p = Point{ ["x"] = 4, ["y"] = 5 };
with
var p: Point = undefined;
@field(p, "x") = 4;
@field(p, "y") = 5;
the trivial disparities between the two notwithstanding.
However, this does not appear to be possible (at least I wasn't able to get it to work) with union(enum)
s. In any case, I would prefer to avoid the above compromise.
How can I initialize a union(enum)
given a comptime string specifying the member in Zig?
This can be done via the @unionInit
builtin.
const std = @import("std");
const Ex = union(enum) { A: u32, B: []const u8 };
pub fn main() void {
const example = @unionInit(Ex, "B", "example");
std.log.info("Example: {any}", .{example});
}
Outputs:
info: Example: test.Ex{ .B = { 101, 120, 97, 109, 112, 108, 101 } }