朱莉娅:如何将一个函数的参数类型定义为元组数组?

时间:2019-05-13 07:41:55

标签: julia

我有一个元组的一维数组,我需要将其传递给定义为的函数

function f(a::Array{Tuple{Vararg{String}}, 1}) 
    #do some processing
end

每个Tuple可以具有任意数量的String元素,但是数组中所有Tuple的元素数量都相同。例如,数组看起来像[("x1","x2"),("y1","y2")][("x1","x2","x3"),("y1","y2","y3")]等。因此,为此使用了Vararg {String}。

现在,当我运行f([("x1","x2"),("y1","y2")])时,它会引发错误

  

“ MethodError:没有与f(:: Array {Tuple {String,String},1})匹配的方法”

我应该如何修改函数定义以使其起作用?

2 个答案:

答案 0 :(得分:4)

之所以得到MethodError,是因为Tuple{Vararg{T}}不是具体类型,因为Vararg的元素数量未指定,并且Julia's type parameters are invariant而不是协变

即使我们有Tuple{Vararg{String, 5}} <: Tuple{Vararg{String}},我们也没有Vector{Tuple{Vararg{String, 5}}} <: Vector{Tuple{Vararg{String}}}

julia> Tuple{Vararg{String, 5}} <: Tuple{Vararg{String}}
true

julia> Vector{Tuple{Vararg{String, 5}}} <: Vector{Tuple{Vararg{String}}}
false

您应该改用以下签名来消除错误

function f(a::Vector{<:Tuple{Vararg{String}}})
# or
function f(a::Vector{T}) where {T <: Tuple{Vararg{String}}

由@crstnbr和@BogumiłKamiński共同建议。这些签名将消除错误,但是,它们不限制Tuple的长度相同。例如,您可以使用以下命令调用这些函数

f([("x1, x2"), ("y1", "y2", "y3"])

由于要确保数组中的元组包含相同数量的元素,因此需要在类型注释中指定此限制。 Vararg的文档提供了有关如何指定元素数的信息。

  

Vararg{T,N}

     

元组类型Tuple的最后一个参数可以是特殊类型Vararg,     表示任意数量的尾随元素。类型Vararg{T,N}     恰好对应于N类型的T元素。 Vararg{T}对应零     或更多类型T的元素。 Vararg元组类型用于表示     varargs方法接受的参数(请参阅有关Varargs函数的部分     在手册中。)

你可以和

一起去
function f(a::Vector{Tuple{Vararg{String, N}}}) where N 
    ...
end

或使用NTuple的紧凑方式

function f(a::Vector{NTuple{N, String}}) where N

end

这些签名将加强您在问题中想要的限制。


注释

您可能是overly specializing your types

正如@BogumiłKamiński在评论部分中指出的那样,最好使用AbstractString类型而不是具体的String类型。

function f(a::Vector{<:NTuple{N, AbstractString}}) where N
...
end

您也可以考虑使用AbstractVector而不是Vector

答案 1 :(得分:1)

您可以将签名修改为

function f(a::Array{<:Tuple{Vararg{String}}, 1})
    #do some processing
end

请注意<:表示Tuple{Vararg{String}}的所有子类型都可以。

但是,仅保留类型信息可能会更容易。该功能将具有完全相同的速度。