在 Julia v0.5+ 中调度函数

Posted

技术标签:

【中文标题】在 Julia v0.5+ 中调度函数【英文标题】:Dispatching on functions in Julia v0.5+ 【发布时间】:2017-02-01 22:43:42 【问题描述】:

根据changelog for Julia 0.5,

现在每个函数和闭包都有自己的类型。

这是否意味着现在可以向高阶函数提供更详细的信息,例如foo(bar :: FunctionFloat64) = ...,与 pre-0.5 不同,bar 的类型不能比 Function 更具体?

如果是这样,这样做的正确方法是什么?如果不是,除了编译器能够更好地优化生成的代码之外,这种变化的实际意义是什么? TIA。

【问题讨论】:

原来type-safe function wrappers的形式可以部分解决这个问题。 【参考方案1】:

不是真的没有。 我明白你的意思,我喜欢它,但这是不可能的。 (当然现在不会,可能永远不会。也许有一天会使用特征。)

让我们看一个例子:foobar

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 的子类型。注意#表示这是一个生成的名字,你不能在写代码的时候把hash放在名字里,但是julia编译器(松散地使用这个词)可以。

为什么它的超超类型不更具体,而不仅仅是功能? 那会是什么? FunctionInt64 还是 FunctionStringjulia 中的函数没有类型签名,方法有。 函数只是多次分派的名称,方法实际上是分派的对象。粗略地说,函数名称表示我应该查看哪个表,而参数的类型(即它的类型签名)是在该表中查找的关键。方法本身就是使用该键返回的内容。

让我们继续我们的示例,看看我们能做什么:

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::Uniontypeof(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。 任一功能都有效。

这具有有限的应用程序,作为白名单。

【讨论】:

谢谢。在尝试typeof 之后,我也有同样的怀疑。

以上是关于在 Julia v0.5+ 中调度函数的主要内容,如果未能解决你的问题,请参考以下文章

在安装 v0.6 的同时在 Ubuntu 16.04 上安装 Julia v0.5

在 Julia 中,为啥 @printf 是宏而不是函数?

在 Julia 中构建非默认构造函数

在 Julia 中运行最小均方函数

在 Julia 的函数中重新分配字典值

AWS Elastic Map Reduce Hive 运行 v0.5?缺少函数:“str_to_map”、“reflect”