Iterate over the types in a Tuple DataType

Viewed 195

Is there a way to iterate over the types contained in a Tuple{...} DataType? For instance, if I have the type Tuple{String, Int}, I'd like to be able to use something like values(Tuple{String, Int}) to return an iterator of String and Int, like this:

julia> collect(values(Tuple{String, Int}))
2-element Array{DataType,1}:
 String
 Int64

But of course that doesn't actually work:

julia> values(Tuple{String, Int})
Tuple{String,Int64}

julia> collect(values(Tuple{String, Int}))
ERROR: MethodError: no method matching length(::Type{Tuple{String,Int64}})
Closest candidates are:
  length(::Core.SimpleVector) at essentials.jl:596
  length(::Base.MethodList) at reflection.jl:852
  length(::Core.MethodTable) at reflection.jl:938
  ...
Stacktrace:
 [1] _similar_for(::UnitRange{Int64}, ::Type{Any}, ::Type{T} where T, ::Base.HasLength) at ./array.jl:576
 [2] _collect(::UnitRange{Int64}, ::Type{T} where T, ::Base.HasEltype, ::Base.HasLength) at ./array.jl:609
 [3] collect(::Type{T} where T) at ./array.jl:603
 [4] top-level scope at REPL[30]:1

I would prefer a solution that does not involve digging into the internals of DataType.

1 Answers

A tuple type is only a DataType. Everything operating on it will have to involve DataTypes -- you're looking for a function of type DataType -> [DataType]. One possible answer is Tuple{String, Int}.parameters. At least in 1.3, Core.Compiler also contains

datatype_fieldtypes(x::DataType) = ccall(:jl_get_fieldtypes, Any, (Any,), x)

which only internal and undocumented, though. Both result in a Core.SimpleVector.

But then I remembered that tuple parts can be treated both as indices and as fields. So it turns out fieldtypes would probably be your favourite:

julia> fieldtypes(Tuple{Int, String})
(Int64, String)

The other methods, however, have the advantage that you can use them with any parametrized type. This often comes in handy in generated functions.

Related