You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I know this is pretty out there, but I was thinking about the interface/inheritance question that's been going around in the community, and it occurred to me: when we say we want something like interfaces, it's kind of a specific version of the more general requirement "I don't care about the exact type of this argument, as long as it satisfies X condition". This is basically what std.meta.trait is all about, giving you convenience functions for patterns like
My thought is, what if the "trait" concept was expanded to the type system. Colloquially any function with the signature fn(type) bool could be known as a trait, and types could be defined by the traits that they satisfy using the new builtin @trait. So let's say you wanted a function that could take any indexable type whose child type is numeric, you could use traits to define it like so:
Functionally, this would be equivalent to specifying a to be anytype and comparing it against isIndexable and isChildNumber at comptime before executing the function. Something that could be done today with something a little contrived like:
// ....fnuseSpecificType(a: anytype) blk: {
constA=@TypeOf(a);
if (isIndexable(A) andisChildNumber(A) {
break :blkstd.meta.Child(A);
} else@compileError("a is not indexable or it does not contain numbers.");
} { ... }
I believe that in addition to the general benefit of giving users an elegant, Zig-like way of defining generic types, this could also provide a solution to the interface "issue" that doesn't require a large change to Zig semantics. Imagine you had a function that expected its parameter to have a field called "len" and a declaration named "init". You could define this using traits like this
With @trait users could create and use type conditions/specifiers in arbitrarily complex fashions while not having to complicate the main logic of their functions. In my opinion it's also very understandable if you're trying to use the code, since it's easy to reason about the contents of an @trait tuple; "Ok, here's the trait being used, it has three conditions (which I know are simply fn(type) bool's), let's see what the conditions are and then I'll know exactly what qualities this type has".
The text was updated successfully, but these errors were encountered:
Hi, thanks for this proposal! It's well thought out, detailed, and contains realistic examples. Unfortunately, we've considered this idea before, in #1669 and #6615. The decision on those issues holds here as well. This feature would add significant complexity to the language, for something that is already achievable with comptime code. It's not clear that this approach is better, because nothing keeps the trait checks consistent with the code that uses the types. Ultimately we think the ergonomic improvements from language support for this feature are not worth the complexity it introduces.
I know this is pretty out there, but I was thinking about the interface/inheritance question that's been going around in the community, and it occurred to me: when we say we want something like interfaces, it's kind of a specific version of the more general requirement "I don't care about the exact type of this argument, as long as it satisfies X condition". This is basically what
std.meta.trait
is all about, giving you convenience functions for patterns likeMy thought is, what if the "trait" concept was expanded to the type system. Colloquially any function with the signature
fn(type) bool
could be known as a trait, and types could be defined by the traits that they satisfy using the new builtin@trait
. So let's say you wanted a function that could take any indexable type whose child type is numeric, you could use traits to define it like so:Traits could even be composed, so the above example could be rewritten as
Functionally, this would be equivalent to specifying
a
to beanytype
and comparing it againstisIndexable
andisChildNumber
at comptime before executing the function. Something that could be done today with something a little contrived like:I believe that in addition to the general benefit of giving users an elegant, Zig-like way of defining generic types, this could also provide a solution to the interface "issue" that doesn't require a large change to Zig semantics. Imagine you had a function that expected its parameter to have a field called "len" and a declaration named "init". You could define this using traits like this
With
@trait
users could create and use type conditions/specifiers in arbitrarily complex fashions while not having to complicate the main logic of their functions. In my opinion it's also very understandable if you're trying to use the code, since it's easy to reason about the contents of an@trait
tuple; "Ok, here's the trait being used, it has three conditions (which I know are simplyfn(type) bool
's), let's see what the conditions are and then I'll know exactly what qualities this type has".The text was updated successfully, but these errors were encountered: