元组类型

typeof a 元组是 Tuple 的子类型:

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

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

与其他数据类型不同,Tuple 类型是协变的 。Julia 中的其他数据类型通常是不变的。从而,

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

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

情况就是如此,因为 Tuple{Number, Number} 被接受,Tuple{Int, Int} 也是如此,因为它也有两个元素,两个元素都是数字。对于 Vector{Int}Vector{Number} 的情况并非如此,因为接受 Vector{Number} 的函数可能希望在这样的向量中存储浮点(例如 1.0)或复数(例如 1+3im)。

元组类型的协方差意味着 Tuple{Number}(再次与 Vector{Number} 不同)实际上是一个抽象类型:

julia> isleaftype(Tuple{Number})
false

julia> isleaftype(Vector{Number})
true

Tuple{Number} 的具体亚型包括 Tuple{Int}Tuple{Float64}Tuple{Rational{BigInt}} 等。

Tuple 类型可以包含终止 Vararg 作为它们的最后一个参数,以指示不确定数量的对象。例如,Tuple{Vararg{Int}} 是包含任意数量的 Ints 的所有元组的类型,可能为零:

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

Tuple{String, Vararg{Int}} 接受由字符串组成的元组,后跟任何数字(可能为零)的 Ints。

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

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

结合协方差,这意味着 Tuple{Vararg{Any}} 描述了任何元组。事实上,Tuple{Vararg{Any}} 只是另一种说法:

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

Vararg 接受第二个数字类型参数,指示其第一个类型参数应该发生多少次。 (默认情况下,如果未指定,则第二个类型参数是可以取任何值的 typevar,这就是为什么在上面的 Varargs 中接受任意数量的 Ints。)以指定的 Vararg 结尾的 Tuple 类型将自动扩展为所请求的数量元素:

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

对于具有指定 VarargNTuple{N, T} 的同源元组,存在符号。在这种表示法中,N 表示元组中元素的数量,T 表示接受的类型。例如,

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)

请注意,超出一定大小的 NTuples 仅显示为 NTuple{N, T},而不是扩展的 Tuple 形式,但它们仍然是相同的类型:

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