a different scenario from this post, where i was looking for a (function) decl of a known name…
in this case, i want to iterate through all of the decls within some container (which seems straightforward)… once i have the names of these decls, i then want to reflect on its type – which i’m not exactly sure how to do…
the tricky part is that i’m looking for (say) all variable decls that implement some generic type… for example, if i had some generic function F(T) how do i find all the decls whose type is an instance of this generic function:
fn F(T: type) type { ... }
var foo = F(u8){};
var bar = F(MyStructType){};
var not_interested = true;
given this container, how can i determine that both foo and bar are of types generated via F???
i’ll probably have follow-on questions about how to programmatically manipulate these discovered values at runtime, but that’s enough for now
You can do that only for the public declarations. std.builtin.Type.Struct is the result of @typeInfo for a struct used as a namespace. The .Struct typeinfo includes the fields and the pubdecls (var and fn).
fn iterate(comptime T: type) void {
inline for (@typeinfo(T).Struct.decls) |decl| {
const name = decl.name;
}
}
@field can access the field, the variable or the function by its name, in a namespace T
again we can use @typeInfo to get metadata for the type of Type.
You cannot do it directly. For foo and bar their type is returned somehow from F. But what you can have is their name and the type information. Their type information is from the type returned by F. I am assuming that F always return a struct; you can add a dummy const F_derived to mark that this struct is constructed from F.
fn F(T: type) type {
return struct {
const F_derived = true;
value: T,
};
}
pub var foo = F(u8);
comptime {
iterate(@Self());
}
fn iterate(comptime T: type) void {
inline for (@typeinfo(T).Struct.decls) |decl| {
const fld = @field(T, decl.name);
const ti = @typeInfo(@TypeOf(fld));
if (ti == .Struct and @hasDecl(fld, "F_derived")) {
@compileLog(decl.name, ti);
}
}
}
@compileLog prints the value and the type of its arguments at compile time.
long story, but i’d actually like to access these variable at run-time – invoking some method inside the struct returned by F…
i also discovered that the string returned @typeName may be sufficient to identify the variables of interest; i “know” which module defines F, etc…
though not my exact use case, suppose i wanted to store (serialize) the values of all matching variables to a file at run-time… i guess this not unlike what json stringify does – although i want to call methods on these variables (which are in fact structs)…
find all public decls in a container, whose type is a struct returned by my F(T);
fetch the value of this decl (at runtime); and
call some save method on this value, where save is defined in the struct returned by my F(T)
i believe i can achieve step 1 using techniques described earlier in the post…
i’m able to call @field as part of step 2, though it’s type is “unknown” (to me, anyway)
i have no clue how to perform step 3 at this point… i know i want to apply .save() to this struct value, but can’t figure out how to coerce it into the specific type i want…
i just ran your snippet with the addition of pub var bar = F(bool).init(true)
incidently, a “better” way to find types returned by F(T) is to look at the @typeName of your FT constant… in your example, it will be "main.F(u8)"…
in my application, the functor F is defined within some “known” module x.y.z which means any decl whose type name starts with x.y.z.F is one that i’m looking for…
i’m just 3 weeks into zig, and continue to be amazed by what i’m learning through this forum…