Julia Language Tuples Tuple types


Example

The typeof a tuple is a subtype of Tuple:

julia> typeof((1, 2, 3))
Tuple{Int64,Int64,Int64}

julia> typeof((1.0, :x, (1, 2)))
Tuple{Float64,Symbol,Tuple{Int64,Int64}}

Unlike other data types, Tuple types are covariant. Other data types in Julia are generally invariant. Thus,

julia> Tuple{Int, Int} <: Tuple{Number, Number}
true

julia> Vector{Int} <: Vector{Number}
false

This is the case because everywhere a Tuple{Number, Number} is accepted, so too would a Tuple{Int, Int}, since it also has two elements, both of which are numbers. That is not the case for a Vector{Int} versus a Vector{Number}, as a function accepting a Vector{Number} may wish to store a floating point (e.g. 1.0) or a complex number (e.g. 1+3im) in such a vector.

The covariance of tuple types means that Tuple{Number} (again unlike Vector{Number}) is actually an abstract type:

julia> isleaftype(Tuple{Number})
false

julia> isleaftype(Vector{Number})
true

Concrete subtypes of Tuple{Number} include Tuple{Int}, Tuple{Float64}, Tuple{Rational{BigInt}}, and so forth.

Tuple types may contain a terminating Vararg as their last parameter to indicate an indefinite number of objects. For instance, Tuple{Vararg{Int}} is the type of all tuples containing any number of Ints, possibly zero:

julia> isa((), Tuple{Vararg{Int}})
true

julia> isa((1,), Tuple{Vararg{Int}})
true

julia> isa((1,2,3,4,5), Tuple{Vararg{Int}})
true

julia> isa((1.0,), Tuple{Vararg{Int}})
false

whereas Tuple{String, Vararg{Int}} accepts tuples consisting of a string, followed by any number (possibly zero) of Ints.

julia> isa(("x", 1, 2), Tuple{String, Vararg{Int}})
true

julia> isa((1, 2), Tuple{String, Vararg{Int}})
false

Combined with co-variance, this means that Tuple{Vararg{Any}} describes any tuple. Indeed, Tuple{Vararg{Any}} is just another way of saying Tuple:

julia> Tuple{Vararg{Any}} == Tuple
true

Vararg accepts a second numeric type parameter indicating how many times exactly its first type parameter should occur. (By default, if unspecified, this second type parameter is a typevar that can take any value, which is why any number of Ints are accepted in the Varargs above.) Tuple types ending in a specified Vararg will automatically be expanded to the requested number of elements:

julia> Tuple{String,Vararg{Int, 3}}
Tuple{String,Int64,Int64,Int64}

Notation exists for homogenous tuples with a specified Vararg: NTuple{N, T}. In this notation, N denotes the number of elements in the tuple, and T denotes the type accepted. For instance,

julia> NTuple{3, Int}
Tuple{Int64,Int64,Int64}

julia> NTuple{10, Int}
NTuple{10,Int64}

julia> ans.types
svec(Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64)

Note that NTuples beyond a certain size are shown simply as NTuple{N, T}, instead of the expanded Tuple form, but they are still the same type:

julia> Tuple{Int,Int,Int,Int,Int,Int,Int,Int,Int,Int}
NTuple{10,Int64}