I’ve been thinking about std_options
and how it effectively doesn’t allow you to use the identifier std_options
in your root source file:
const std = @import("std");
pub const std_options = enum {
herpes_simplex_virus_1,
herpes_simplex_virus_2
};
pub fn main() void {
std.debug.print("You've got {}!", .{std_options.herpes_simplex_virus_1});
}
error: expected type 'std.Options', found 'type'
pub const options: Options = if (@hasDecl(root, "std_options")) root.std_options else .{};
Granted, nobody is going to use std_options
as an identifier, unless you work for the CDC or something… but the std library serves as an example for us all, so maybe it could avoid using @hasDecl
on the root source file?
- hard to discover the type of
std_options
before being hit with a compile error (no “goto definition”) - can’t namespace the identifier
- large “action at a distance” feel
I came up with a couple options for std_options:
- Make std a generic functions that has
std_options
are arguments. Not sure this is really practical.std
is a namespace, so if we make it a generic function then we have to enclose std in some other namespace… - Make std.log a generic function that accepts a log level? This pattern could be extended to all things in
std
with comptime options. - Somehow write a
std.withOptions()
function that returns a customized std.
I prototyped option 3, but it has the downside of now being required to initialize std, and there’s a good amount of comptime
shenanigains.
std2.zig
// My version of std that doesn't polute the root namespace with std_options
options: Options = .{},
pub const LogLevel = enum { debug, info, warn, err };
pub const Options = struct {
log_level: LogLevel = .err,
};
pub fn withOptions(comptime options: Options) @This() {
return @This(){ .options = options };
}
pub fn warn(comptime self: @This(), message: []const u8) void {
if (comptime self.options.log_level == .warn) {
std.debug.print("WARN: {s}\n", .{message});
}
}
const std = @import("std");
test.zig
// weird, now I have to initialize std2
pub const std2 = @import("std2.zig"){};
test {
std2.warn("this message doesnt print."); // default log level is err
const std2_with_options = comptime @import("std2.zig").withOptions(.{ .log_level = .warn });
std2_with_options.warn("Hello warn!");
}