Sorry for digging an old topic, but sharing in case someone need it: In my case, I want to create a busybox-style binary so I have one main to dispatch to other main in files.
Instead of making an enum listing all the file name and another switch listing the file names yet again, you can use a union(enum):
const std = @import("std");
const Example = union(enum) {
unknown: void,
hello_world: @import("hello_world.zig"),
identity: @import("identity.zig"),
lbbroker: @import("lbbroker.zig"),
multiple_socket: @import("multiple_socket.zig"),
multithreaded_relay: @import("multithreaded_relay.zig"),
multithreaded_server: @import("multithreaded_server.zig"),
psenv: @import("psenv.zig"),
request_reply: @import("request_reply.zig"),
rtdealer: @import("rtdealer.zig"),
rtreq: @import("rtreq.zig"),
sync: @import("sync.zig"),
task: @import("task.zig"),
task2: @import("task2.zig"),
version: @import("version.zig"),
weather_update: @import("weather_update.zig"),
const Name = std.meta.Tag(Example);
const names = std.StaticStringMap(Example.Name).initEnum();
};
pub fn main(init: std.process.Init) !void {
const args = try init.minimal.args.toSlice(init.arena.allocator());
const selected: Example.Name = if (args.len < 2) .unknown else Example.names.get(args[1]) orelse .unknown;
return switch (selected) {
.unknown => {
if (args.len >= 2) std.debug.print("unknown example: {s}\n", .{args[1]});
std.debug.print("pick one: ", .{});
for (Example.names.keys(), 0..) |key, j| {
if (j != 0) std.debug.print(", ", .{});
std.debug.print("{s}", .{key});
}
std.debug.print("\n", .{});
std.process.exit(1);
},
// TODO: strip out the args if necessary
inline else => |name| @FieldType(Example, @tagName(name)).main(init),
};
}
The inline else => |name| @FieldType(Example, @tagName(name)).main(init) will do the job of deduplicating the enumeration.
I suppose this might be useful if you have a bunch of files exporting the same interface.