在Julia的一个函数中的联合型专业化



假设我有一个函数,其中c关键字参数是Union类型。根据c的类型,我想在函数中做一些事情:

function foo(a :: Integer, b :: AbstractFloat; c :: Union{Integer, AbstractFloat} = nothing)
if typeof(c) <: AbstractFloat
d = c / pi
elseif typeof(c) <: Integer
d = typeof(b)(c ^ 2)
end
return d
end

这是处理这种情况的正确方法吗?我应该使用多重调度来实现更高效的实现吗?我也在考虑这里的表现。

谢谢。

一些评论。

本部分:

c::Union{Integer, AbstractFloat} = nothing

不会编译,则必须编写c::Union{Nothing, Integer, AbstractFloat} = nothing

通常,typeof(c) <: AbstractFloat应该由编译器进行优化,因为编译器知道您要传递的c的确切类型,所以这种风格不应该影响代码的性能。

然而,有两个考虑因素:

  1. 使用多种方法可能会产生更干净的代码
  2. 如果使用Union,则在定义方法时必须更加小心,以避免调度不明确。以下是一个示例:
julia> f(x::Int, y::Union{Int, Float64}) = "f1"
f (generic function with 1 method)
julia> f(x::Integer, y::Int) = "f2"
f (generic function with 2 methods)
julia> f(1, 1)
ERROR: MethodError: f(::Int64, ::Int64) is ambiguous.

这有时被认为是令人惊讶的(尽管从技术上讲这是一种正确的行为(

编辑。下面是一个编译器没有抱怨的例子,因为它总是可以建立一个更具体的方法:

julia> g(x::Int, y::Union{Int, Float64}) = "f1"
g (generic function with 1 method)
julia> g(x::Integer, y::Union{Int, Float64}) = "f2"
g (generic function with 2 methods)
julia> g(1, 1)
"f1"

最新更新