现在每个函数和闭包都有自己的类型。
这是否意味着现在可以向更高阶的功能提供更详细的信息,例如: foo(bar :: Function{Float64}) = ...
,而不是0.5之前,其中bar
的类型不能比Function
更具体?
如果是这样,这样做的正确方法是什么?如果没有,除了编译器能够更好地优化生成的代码之外,这个变化的实际导入是什么? TIA。
答案 0 :(得分:5)
不是真的没有。 我看到你得到了什么,我喜欢它,但这是不可能的。 (当然不是,现在可能不会。也许不会使用特征。)
让我们看一个示例: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中的函数,没有类型签名,方法可以。
一个函数只是多个调度的名称,一个方法实际上是调度到的。粗略地说,函数名称表示我应该查看哪个表,并且参数的类型(即它的类型签名)是在该表中查找的关键。该方法本身就是使用该密钥返回的内容。
让我们继续我们的示例,看看我们能做些什么:
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
。
这两种功能都有效。
这是一个有限的应用程序,作为白名单。