大括号内或外的`where`关键字的区别

mih*_*mek 11 where-clause julia

之间有什么区别

function foo(a::Adjoint{Float64, Matrix{T}} where T)
    return 0
end
Run Code Online (Sandbox Code Playgroud)

function foo(a::Adjoint{Float64, Matrix{T} where T})
    return 1
end
Run Code Online (Sandbox Code Playgroud)

(注意花括号的位置。)

julia> methods(foo)
# 2 methods for generic function "foo":
[1] foo(a::Adjoint{Float64,Array{T,2}} where T) in Main at REPL[247]:2
[2] foo(a::Adjoint{Float64,Array{T,2} where T}) in Main at REPL[248]:2
Run Code Online (Sandbox Code Playgroud)

似乎在这两种情况下,函数都会接受 Matrix 类型的伴随T?我无法弄清楚这两个功能之间的区别是什么。

Jak*_*sen 7

第一个是 unionall 类型,第二个是具体类型:

julia> isconcretetype(Adjoint{Float64, Matrix{T} where T})
true

julia> isconcretetype(Adjoint{Float64, Matrix{T}} where T)
false

julia> (Adjoint{Float64, Matrix{T}} where T) isa Core.UnionAll
true
Run Code Online (Sandbox Code Playgroud)

第一个是Matrix包含某种类型a 的无限伴随词集。换句话说,我们可以想象用伪代码表示无限集,例如:

Set([Adjoint{Float64, T} for T in all_possible_types])

而第二个是Matrix某种类型的伴随包装 a ,或者换句话说:

Adjoint{Float64, Matrix_of_any_type}.

你几乎总是想要前者,而不是后者。几乎没有理由构造一个可以包含 any 的伴随Matrix,通常你只需要一个类型的伴随。

区别更明显Vector

  • Vector{Vector{T}} where T 是一个 unionall 表示所有同类型向量的向量。
  • Vector{Vector{T} where T}是一个包含特定元素类型的向量Vector{T} where T


Cam*_*nek 5

Vector{Vector{T} where T}下面是一个示例,说明了vs的更简单情况的差异Vector{Vector{T}} where T

首先创建一些类型别名:

julia> const InsideWhere = Vector{Vector{T} where T}
Array{Array{T,1} where T,1}

julia> const OutsideWhere = Vector{Vector{T}} where T
Array{Array{T,1},1} where T
Run Code Online (Sandbox Code Playgroud)

如果可能,默认数组构造函数会将元素提升为通用类型:

julia> x = [[1, 2], [1.2, 3.4]]
2-element Array{Array{Float64,1},1}:
 [1.0, 2.0]
 [1.2, 3.4]

julia> x isa InsideWhere
false

julia> x isa OutsideWhere
true
Run Code Online (Sandbox Code Playgroud)

但是通过使用类型化数组文字,我们可以避免自动升级:

julia> y = ( Vector{T} where T )[[1, 2], [1.2, 3.4]]
2-element Array{Array{T,1} where T,1}:
 [1, 2]
 [1.2, 3.4]

julia> y isa InsideWhere
true

julia> y isa OutsideWhere
false
Run Code Online (Sandbox Code Playgroud)