It is clear that the original intent of Tuple#types was to return a proper tuple of types that can be usefully iterated over at runtime.
However its behavior indirectly changed somewhere along the way without checking whether it is still useful (specs were updated instead, and the nuance in documentation was lost as well). Now tuple.types is literally the same as typeof(tuple), and I don't see any reason for it to exist in this state.
Strangely enough, within the codebase there is a Tuple.types method that behaves exactly as everyone would expect, but it's hidden in specs.
What I want: iterate over a Tuple's types at runtime, like so:
def create_random_tuple
{"a" == "a" ? 5 : 5u8, "string"}
end
struct Tuple
def self.types
{% begin %}
{
{% for type in T %}
{{type}},
{% end %}
}
{% end %}
end
end
a = create_random_tuple
typeof(a).types.each do |t|
p t
# (Int32 | UInt8)
# String
end
but without adding my own extension to Tuple, and without this workaround that @Groogy showed.
At the moment this seems impossible:
def create_random_tuple
{"a" == "a" ? 5 : 5u8, "string"}
end
a = create_random_tuple
a.types.each do |t|
p t
end
# Error in line 6: undefined method 'each' for Tuple(Int32 | UInt8, String):Class
Should we add Tuple.types then?
Something like Tuple.types seems like a good addition (or restoration).
I think that NamedTuple.types should also exist returning a named tuple of key -> type.
But then, if we think in the broader feature, we are looking for a way to get the type arguments of generic types in runtime. Tuple and NamedType are special cases because they don't exhibit in their declaration the T argument, but it is still there.
So if we add expr.class.generic_arguments for all generic types might be the more complete solution. (yet, if we add just for tuple and named tuple i'm fine).
The generic_argument would return a tuple when positional arguments are used or a named tuple when named arguments are used (in well, named tuples). For cases like StaticArray though, the returning tuple will contain the length numeric argument.
The future planning is all fine but is it correct that Tuple#types is entirely useless at the moment?
I agree @oprypin . BTW a shorter implementation would be Tuple.new(*{{T}})
Most helpful comment
Should we add
Tuple.typesthen?