#runtime type instantiation

1 messages · Page 1 of 1 (latest)

urban belfry
#

i want to instantiate a struct based on some type, but the type is only known after comparing some string at runtime. Is there a way to do this? Seems like type is only available at comptime.

eg

pub fn Foo(comptime T: type) type {
   return struct { ... }
}

pub fn doSomething(input: []const u8) {
    const my_type = if (std.mem.eql(u8, &input, some_string)) Foo else Bar;
}

(Bar is some other type)
(this doesn't work, but can I do something like this?)

upbeat cypress
#

types dont exist runtime

urban belfry
#

hmm, yeah i think i kinda got that from previous questions, wondering if it's possible to express the above at runtime at all

#

or it's just impossible?

upbeat cypress
#

what you can do is:

const Thing = enum {
  Bar,
  Foo,
  Invalid,
};

pub fn doSomething(input: []const u8) void {
  switch (std.meta.stringToEnum(Thing, input) orelse .Invalid) {
    .Bar => ... do bar stuff ..,
    .Foo => ... do foo stuff ..,
    .Invalid => @panic("invalid input"),
  }
}
white valve
#
switch (std.mem.eql(u8, u8, input, some_string)) {
    inline true, false => |is_eql| {
        const MyType = if (is_eql) Foo else Bar;
        _ = MyType;
    },
}

might work lol

urban belfry
#

that looks cursed

white valve
white valve
#

zig just makes it look as cursed as it is

#

essentially, it works on the basis of generating multiple distinct runtime branches

#

it generates a branch for true and false

#

for each of which the value is comptime-known within the generated branch

#

since it's comptime-known, you can branch on that value at comptime

#

whilst not duplicating the code manually

#

the alternative would be to write it out manually:

switch (std.mem.eql(u8, input, some_string)) {
    true => {
        const MyType = Foo;
        _ = MyType;
    },
    false => {
        const MyType = Bar;
        _ = MyType;
    },
}

(and then re-expressed as an if else)

urban belfry
#

hmm but the comptime-known portion would only be within the branches themselves, right? is this trick possible if i want to assign instead, eg. const my_type = switch (...

#

maybe i'll just generate all the branches bc there aren't many permutations of the types i need

upbeat cypress
#

you can write anytype function which you pass the constructed type from switch

#

or generic function with type as comptime parameter and whatever other input you need

white valve
#

the switch itself branches on a runtime-known value

#

the captures are only comptime-known within their own branch