-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tuple type introspection via indexing/iteration #22687
Conversation
+1, I've definitely wanted this lately. |
See also #22350. |
# typeof(Tuple) is simply DataType | ||
_iteratorsize(::Type{T}) where {T<:Tuple} = (@_pure_meta; isvatuple(T) ? IsInfinite() : HasLength()) | ||
_length(::HasLength, T::Type{<:Tuple}) = length(T.types) | ||
_length(::IsInfinite, T::Type{<:Tuple}) = typemax(Int) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
little odd for something that's supposed to be infinite to return a finite length?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it throw an error instead? (I could just delete this line and it would throw a MethodError
in that case.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, length
usually gives a MethodError on infinite iterators.
It also might be useful to export a new function like (Basically, this just means cleaning up and exporting |
One problem here is that Ideally, I'd like to be able to introspect the components of unions in the same way, so adding some additional methods to this PR would do the trick. However, I'm confused by the behavior of dispatch here: julia> foo(::Type{<:Union}) = 1
foo(::Type{<:Tuple}) = 2
foo(::Type{Union{<:Tuple}}) = 3
julia> foo(Union{Tuple{Int},Tuple{Any}})
2 I would have expected |
Ref #11547. |
In #22051, I observed that while accessing the fields of the tuple datatype is generally not valid (because of the possibility of Union), and thus also not possible to infer, the |
This is just
This is just
|
@vtjnash, thanks for the tip about In order to use this effectively, however, it would be good to export and document some version of |
Yes, in this case it's important to distinguish looking at the structure of a type (which is generally painful and difficult to get right) from "type-domain indexing", which is what
That's telling you what you'd get from accessing an instance of the given type. |
While a better introspection API sounds useful, I'm not sure I like the julia> Int[1]
1-element Array{Int64,1}:
1
julia> Tuple{Int}[(1,)]
1-element Array{Tuple{Int64},1}:
(1,)
julia> Tuple{Int}[1] # surprise!
Int64 Putting this behind |
Anything that makes working with these easier is very welcome to me. :) Would a |
I'm not so concerned about iteration (I can always loop over indices), but I am concerned with knowing the length of the tuple, whether it is a vararg tuple, and documenting this introspection technique; having multiple packages looking at undocumented internals is broken. It would also be nice to make sure these things were known at compile time, but this is an optimization that could be added later if needed. I will close this PR since the consensus seems to be against indexing (and I wasn't even aware of #11547). Will try again with another PR based on |
This works nicely:
|
Or more succinctly, |
Cool. Is there a way to get fieldtype to inline? |
Boiled down the type instability to this:
|
@martinholters I'd argue that it's really the |
This should be fully inferable. Dunno why though.
|
Safer:
I'm gathering that if you are going to use types in inference, they should be passed around wrapped in Vals, and unpacked at point of use with |
This PR simplifies introspection of tuple types by allowing you to iterate/index tuple types almost as if they were simply a tuple of types. For example, it allows you to do:
Without this PR, you have to do a lot of digging through Julia internals to do introspection of tuple types (via the undocumented
T.types
field), and it is especially difficult to introspect vararg tuple types (via undocumented functions likeBase.unwrapva
).I encountered this when generalizing tuple conversion for PyCall (JuliaPy/PyCall.jl#404), and the difficulty of tuple introspection has also caused some fragility in JLD (#10999).