ioanaci
Afaict they have police officers regulating traffic instead. Not much difference in this particular discussion.
You're right Zig isn't quite as powerful, but you don't need type erasure if you have enough monomorphization. It's a bit annoying to use since you have to capture the comptime version of b inside the inline switch prongs, and get_value does need to take a comptime bool instead of a runtime one. It's functionally the same, except that instead of using the bool to prove the type of the type-erased value is correct and delaying the actual if (b) check to runtime, we're moving it to compile time and instead proving that b has the right value for each case, then generating specialized code.
This does NOT mean that it isn't dependent on user input, the call do_thing(get_user_input()) would absolutely work. do_thing has no compile-time parameters at all.
I don't have the natToString thing because it's a bit more annoying in Zig and would obscure the point.
const std = @import("std");
fn get_value(comptime b: bool) if (b) u32 else []const u8 {
if (b) return 12
else return "string";
}
fn do_thing(b: bool) void {
switch (b) {
inline true => |known_b| std.log.info("{d}", .{get_value(known_b)}),
inline false => |known_b| std.log.info("{s}", .{get_value(known_b)}),
}
}
pub fn main() void {
do_thing(true);
do_thing(false);
}
You could define a function fn pick_type(comptime b: bool) type {
if (b) return u32 else return []const u8;
}
and change the signature fn get_value(comptime b: bool) pick_type(b)
if you wish.Perhaps more convincingly, you can use inline for with a similar effect. It's obviously horrible code nobody would ever write but I think it might illustrate the point.
fn do_thing(b: bool) void {
inline for (0..2) |i| { // go through all bool variants
const known_b = (i != 0);
if (known_b == b) {
// Essentially what we have now is a known_b which is proven
// at compile-time to be equal to whatever runtime b we have.
// So we're free to do any kind of dependent type things we'd like
// with this value.
const value = get_value(known_b);
// Here we know the type of value but it still depends on the runtime b.
if (known_b) std.log.info("{d}", .{value}) // treated as an int
else std.log.info("{s}", .{value}); // treated as a string
// We can also just decide based on the type of value at this point.
if (@TypeOf(value) == u32) ... else ...;
// Or, a switch
switch (@TypeOf(value)) {
u32 => ...,
[]const u8 => ...,
}
}
}
}