在 Julia v0.5+ 中调度函数
Dispatching on functions in Julia v0.5+
Each function and closure now has its own type.
这是否意味着现在可以向高阶函数提供更详细的信息,例如foo(bar :: Function{Float64}) = ...
,与 0.5 之前的版本相反,其中 bar
的类型不能比 Function
?
更具体
如果是这样,正确的做法是什么?如果不是,除了编译器能够更好地优化生成的代码之外,此更改的实际意义是什么? TIA.
不是真的没有。
我明白你的意思,我喜欢它,但这是不可能的。
(当然不是现在,可能永远不会。也许有一天会使用特征。)
让我们看一个例子:foo
和bar
julia> foo(x::String) = println(x)
foo (generic function with 1 method)
julia> foo(x::Int64) = println(x+1)
foo (generic function with 2 methods)
julia> bar(x...) = println(x)
bar (generic function with 1 method)
foo
的类型层次结构是什么?
julia> typeof(foo)
#foo
julia> supertype(typeof(foo))
Function
julia> supertype(supertype(typeof(foo)))
Any
所以我们看到 foo
函数的类型是 #foo
,它是 Function
的子类型。请注意,#
表示这是一个生成的名称,您不能在编写代码时将哈希放入名称中,但 julia 编译器(宽松地使用该术语)可以。
为什么它的超超类型不只是功能更具体?
那会是什么? Function{Int64}
还是 Function{String}
?
julia 中的函数没有类型签名,方法有。
函数只是多重分派的名称,方法实际上是分派的对象。粗略地说,函数名称表示我应该查看哪个 table,参数的类型(即它的类型签名)是查找的关键,在那个 table 中。该方法本身就是使用该键返回的内容。
所以让我们继续我们的例子,看看我们能做什么:
julia> dothing(f::typeof(foo)) = f(rand([randstring(), rand(Int64)]))
dothing (generic function with 1 method)
julia> dothing(foo)
3139374763834167054
julia> dothing(foo)
Ed2kNGrd
julia> dothing(bar)
ERROR: MethodError: no method matching dothing(::#bar)
Closest candidates are:
dothing(::#foo) at REPL[11]:1
所以我们成功限制了dothing
,只取一个#foo
作为它的论点。当你给它 #bar
时,它会抛出一个错误。
这并不是很有用,因为 foo
函数是唯一类型为 #foo
.
的东西
不过我们可以使用 Union
:
julia> dootherthing(f::Union{typeof(foo),typeof(bar)}) = f(rand([randstring(), rand(Int64)]))
dootherthing (generic function with 1 method)
julia> dootherthing(foo)
9107791406050657562
julia> dootherthing(foo)
SmB2Xmw8
julia> dootherthing(bar)
("1IpZIMnx",)
julia> dootherthing(bar)
(-6356894350805213697,)
julia> dootherthing(str)
ERROR: UndefVarError: str not defined
julia> dootherthing(string)
ERROR: MethodError: no method matching dootherthing(::Base.#string)
Closest candidates are:
dootherthing(::Union{#bar,#foo}) at REPL[19]:1
dootherthing
接受 #foo
或 #bar
。
这两个函数都有效。
作为白名单,这具有有限的应用。
Each function and closure now has its own type.
这是否意味着现在可以向高阶函数提供更详细的信息,例如foo(bar :: Function{Float64}) = ...
,与 0.5 之前的版本相反,其中 bar
的类型不能比 Function
?
如果是这样,正确的做法是什么?如果不是,除了编译器能够更好地优化生成的代码之外,此更改的实际意义是什么? TIA.
不是真的没有。 我明白你的意思,我喜欢它,但这是不可能的。 (当然不是现在,可能永远不会。也许有一天会使用特征。)
让我们看一个例子:foo
和bar
julia> foo(x::String) = println(x)
foo (generic function with 1 method)
julia> foo(x::Int64) = println(x+1)
foo (generic function with 2 methods)
julia> bar(x...) = println(x)
bar (generic function with 1 method)
foo
的类型层次结构是什么?
julia> typeof(foo)
#foo
julia> supertype(typeof(foo))
Function
julia> supertype(supertype(typeof(foo)))
Any
所以我们看到 foo
函数的类型是 #foo
,它是 Function
的子类型。请注意,#
表示这是一个生成的名称,您不能在编写代码时将哈希放入名称中,但 julia 编译器(宽松地使用该术语)可以。
为什么它的超超类型不只是功能更具体?
那会是什么? Function{Int64}
还是 Function{String}
?
julia 中的函数没有类型签名,方法有。
函数只是多重分派的名称,方法实际上是分派的对象。粗略地说,函数名称表示我应该查看哪个 table,参数的类型(即它的类型签名)是查找的关键,在那个 table 中。该方法本身就是使用该键返回的内容。
所以让我们继续我们的例子,看看我们能做什么:
julia> dothing(f::typeof(foo)) = f(rand([randstring(), rand(Int64)]))
dothing (generic function with 1 method)
julia> dothing(foo)
3139374763834167054
julia> dothing(foo)
Ed2kNGrd
julia> dothing(bar)
ERROR: MethodError: no method matching dothing(::#bar)
Closest candidates are:
dothing(::#foo) at REPL[11]:1
所以我们成功限制了dothing
,只取一个#foo
作为它的论点。当你给它 #bar
时,它会抛出一个错误。
这并不是很有用,因为 foo
函数是唯一类型为 #foo
.
不过我们可以使用 Union
:
julia> dootherthing(f::Union{typeof(foo),typeof(bar)}) = f(rand([randstring(), rand(Int64)]))
dootherthing (generic function with 1 method)
julia> dootherthing(foo)
9107791406050657562
julia> dootherthing(foo)
SmB2Xmw8
julia> dootherthing(bar)
("1IpZIMnx",)
julia> dootherthing(bar)
(-6356894350805213697,)
julia> dootherthing(str)
ERROR: UndefVarError: str not defined
julia> dootherthing(string)
ERROR: MethodError: no method matching dootherthing(::Base.#string)
Closest candidates are:
dootherthing(::Union{#bar,#foo}) at REPL[19]:1
dootherthing
接受 #foo
或 #bar
。
这两个函数都有效。
作为白名单,这具有有限的应用。