元组类型
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}}
是包含任意数量的 Int
s 的所有元组的类型,可能为零:
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}}
接受由字符串组成的元组,后跟任何数字(可能为零)的 Int
s。
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,这就是为什么在上面的 Vararg
s 中接受任意数量的 Int
s。)以指定的 Vararg
结尾的 Tuple
类型将自动扩展为所请求的数量元素:
julia> Tuple{String,Vararg{Int, 3}}
Tuple{String,Int64,Int64,Int64}
对于具有指定 Vararg
:NTuple{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)
请注意,超出一定大小的 NTuple
s 仅显示为 NTuple{N, T}
,而不是扩展的 Tuple
形式,但它们仍然是相同的类型:
julia> Tuple{Int,Int,Int,Int,Int,Int,Int,Int,Int,Int}
NTuple{10,Int64}