This is what I’m trying to do right now (I really wish *anytype
and []anytype
and stuff existed, this isn’t the first, second, or third time I’ve wanted them), and I’m unpacking everything manually. I’m going to give it rest for now and come back tonight.
Are you trying to constrain something to being a pointer or slice?
Here’s the thing… if you break down what anytype
actually is, it covers both of those cases:
*anytype
→ *T
→ anytype
[]anytype
→ []T
→ anytype
It’s a catch all because a pointer to some type is just another type itself… thus is covered under the umbrella of anytype
.
I’m not discounting your idea though because it sounds like you want “constraints”.
obviously. It is just so much easier to to []anytpe
than to do the comptime code(on 3 lines, but this takes zero lines and shows intent much better). Yes. it is a form of constraint: it is a very lightweight version that covers a good portion of cases (?anytype
, *const anytype
, etc…) for basically no extra complexity and its highly intuitive: I actually expected it to work. This requires no extra syntax, so I don’t think it is appropriate to group it with other constaint solutions with often large amounts of complexity.
But that was a little off topic, I still cant solve my problem. It is still mind blowing to me that given a function body, I can’t get the name of the function in comptime. C, C++, rust, java, python, lisp, … you can it in every one of them. I’m struggling to think of similar langauges where this isn’t possible.
At the time I wanted to pass in the type to give the user more info as to what was expected because anytype doesn’t give that info to the person looked at the signature or docs.
I’ve since reworked it to be down to:
pub noinline fn run_count_cross(
comptime opt: Options,
invokes: usize,
comptime funcs: anytype,
comptime args: anytype,
) [funcs.len * args.len]Data {
That is much simple and it works too, but does lack any info that it expected funcs to be an array of functions with a single type and args to also be an array of natives or tuples. I may try to find a way to reintroduct the FuncType argument (and then type funcs as [N]FuncType
since it wont let me make a slice of function bodies. Then args could be typed [L]ArgsType(FuncType)
if I can find a way to write ArgsType that returns a struct type that has the shape of the args to the functions. You get an array of the arguments which I think was the wrong way to present that information since it in the wrong for to use for @call
- should have been a tuple.
Also take a look at this topic where we played around with similar ideas
I saw that and actually tried to implement a version of it. Twisted and amazing idea.
Still trying to get the function names, lol. That’s the last piece of this lol.
having a struct that keeps track of the function name and function body (that still has to be fill in by hand) is a no-go. This is for a general micobenchmarking tool and I think that is expecting too much of the user.
If this was a one off thing, Id totally do that, but this would need to be filled in every time you used the benchmarking lib.
You can use this to document the parameters: What are the best param documentation patterns for Zig? - #5 by squeek502
Additionally you can add a compile time check + @compileError
in the function body.
not a good solution – not even a close to good enough one. And I already know that, but I find it so hacky. It reminds me of the early days of C++ templates that were way more powerful than originally understoof and when people started to hack at them, the language committee ddnt really start addressing those valid use cases until c++17/20 so you have over a decade of bad templates message with confusing results were just incredibly weird and a huge “huh” factor.
Anytime I do zig meta programming, I find so many issues. It is an a huge amount of work to do some rather trivial things. I hope the language improves in that area, but given that interfaces have been shot down multiple times, hopefully all the ugly hacks and bad bad compilation messages will cause a re-evaluation of that.
I tried to write something give a struct, would see if another struct conformed to its interface, but if there are interfaces to those types, I tried to recurse and there is just no way to stop the recursion so it would get into loops, and I could never get it to work on certain things so I abandoned it.
I need to find a way to linearize the type tree at compile type and then just run down the list of types and do a shallow check of each. But I havent though of a way to do that yet. (I have put a __impl\__ = OtherStruct
so signify this struct was to implement the other.
Now that I’m a little better, I think I might return to that and try to take it in pieces: first linearize the type tree.
YES! I’m just not sure which is better?
fn WhoAreYou(_: anytype) type {
return struct {
pub const the = @typeName(@This());
pub const who = the[0 .. the.len - 3][26..];
};
}
fn HiMyNameIs(_: anytype) type {
return struct {
pub const slim = @typeName(@This());
pub const shady = slim[0 .. slim.len - 3][27..];
};
}
test "pp" {
const T = WhoAreYou(bitcount_bk);
const S = HiMyNameIs(bitcount_bk);
std.debug.print("\n{s}\n", .{T.who});
std.debug.print("\n{s}\n", .{S.shady});
std.testing.e
}
It works, and I have idea why. I’ll look into this later to see the implications of this. but thank you very much.
HT @chung-leong nice hack.
Not a problem:
const AsDefined = struct {
a: usize = 0,
};
const Synonym = AsDefined;
test "which name?" {
std.debug.print("\n{s}\n", .{@typeName(AsDefined)});
std.debug.print("{s}\n", .{@typeName(Synonym)});
}
Both will print filename.AsDefined
.