# 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 `Int`s, 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 `Int`s.

``````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 `Int`s are accepted in the `Vararg`s 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 `NTuple`s 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}
``````