I came up with the following⌠This is about what i need.
pub const spsa: bool = false; // or true :)
pub const current_terms = if (spsa) &tunable_terms else &default_terms;
pub const default_terms: Terms = .{};
pub var tunable_terms: Terms = if (spsa) default_terms else void;
pub const Terms = struct {
reversed_futility_pruning: _reversed_futility_pruning = .{},
pub const _reversed_futility_pruning = struct {
max_depth: Tunable(i32) = tunable(i32, 6, 2, 8, 1),
base_margin: Tunable(i32) = tunable(i32, 21, 10, 60, 10),
improving_margin: Tunable(i32) = tunable(i32, 40, 20, 100, 10),
not_improving_margin: Tunable(i32) = tunable(i32, 74, 20, 120, 10),
};
};
inline fn tunable(comptime T: type, comptime value: T, min: T, max: T, step: T) Tunable(T) {
return switch (spsa) {
false => Tunable(T).init(value),
true => Tunable(T).init(value, min, max, step),
};
}
pub fn Tunable(comptime T: type) type {
return switch (spsa) {
false => ConstantEntry(T),
true => TunableEntry(T),
};
}
pub fn ConstantEntry(comptime T: type) type {
return struct {
const Self = @This();
v: T,
inline fn init(value: T) Self {
return .{ .v = value };
}
};
}
pub fn TunableEntry(comptime T: type) type {
return struct {
const Self = @This();
v: T,
min: T,
max: T,
step: T,
inline fn init(value: T, min: T, max: T, step: T) Self {
return .{ . v = value, .min = min, .max = max, .step = step };
}
};
}
main
std.debug.print("tunable size {}\n\n", .{ @sizeOf(Tunable(i32)) } );
std.debug.print("before \n{}\n", . { current_terms.reversed_futility_pruning });
current_terms.reversed_futility_pruning.max_depth.v = 424242; // does not compile when spsa == false
std.debug.print("after \n{}\n", . { current_terms.reversed_futility_pruning });