julia中具有相同变量类型的多个分派

julia中具有相同变量类型的多个分派,julia,Julia,通常,如果函数中的一个参数更改了数据类型(例如Float64vsComplex{Float64}),那么julia中的多重分派是简单的。如果参数是整数,我需要两个函数,一个用于偶数,另一个用于奇数,那么如何实现多个分派?正如@logankilpatrick所指出的,分派系统是基于类型的。然而,你所要表达的是一种众所周知的特质 基本上你的代码看起来像 myfunc(num) = iseven(num) ? _even_func(num) : _odd_func(num) 正如@logankilp

通常,如果函数中的一个参数更改了数据类型(例如
Float64
vs
Complex{Float64}
),那么julia中的多重分派是简单的。如果参数是整数,我需要两个函数,一个用于偶数,另一个用于奇数,那么如何实现多个分派?

正如@logankilpatrick所指出的,分派系统是基于类型的。然而,你所要表达的是一种众所周知的特质

基本上你的代码看起来像

myfunc(num) = iseven(num) ? _even_func(num) : _odd_func(num)

正如@logankilpatrick指出的,调度系统是基于类型的。然而,你所要表达的是一种众所周知的特质

基本上你的代码看起来像

myfunc(num) = iseven(num) ? _even_func(num) : _odd_func(num)

所以这里有另一个选择,我认为它更干净,更面向多个分派(由同事提供)。让我们认为
N
是要检查的自然数,我想要两个函数根据
N
是偶数还是奇数执行不同的操作。因此

boolN = rem(N,2) == 0
(...)
function f1(::Val{true}, ...)
(...)
end
function f1(::Val{false}, ...)
(...)
end
要调用函数,只需执行以下操作

f1(Val(boolN))

所以这里有另一个选择,我认为它更干净,更面向多个分派(由同事提供)。让我们认为
N
是要检查的自然数,我想要两个函数根据
N
是偶数还是奇数执行不同的操作。因此

boolN = rem(N,2) == 0
(...)
function f1(::Val{true}, ...)
(...)
end
function f1(::Val{false}, ...)
(...)
end
要调用函数,只需执行以下操作

f1(Val(boolN))

我希望通过类型分派,在检查奇数与偶数之后,您最终仍然在调用,因此,最经济的代码(没有运行时惩罚)是让调用方检查参数并调用适当的函数

如果由于某种与运行时效率无关的原因,您仍然必须基于类型,下面是这样一个示例:

abstract type HasParity end

struct Odd <: HasParity
    i::Int64
    Odd(i::Integer) = new(isodd(i) ? i : error("not odd"))
end

struct Even <: HasParity
    i::Int64
    Even(i::Integer) = new(iseven(i) ? i : error("not even"))
end

parity(i) = return iseven(i) ? Even(i) : Odd(i)

foo(i::Odd) = println("$i is odd.")
foo(i::Even) = println("$i is even.")


for n  in 1:4
    k::HasParity = parity(n)
    foo(k)
end
抽象类型HasParity end

struct Odd我希望通过类型分派,在检查奇数与偶数之后,您最终仍然在调用,因此,最经济的代码(不需要运行时惩罚)是让调用方检查参数并调用适当的函数

如果由于某种与运行时效率无关的原因,您仍然必须基于类型,下面是这样一个示例:

abstract type HasParity end

struct Odd <: HasParity
    i::Int64
    Odd(i::Integer) = new(isodd(i) ? i : error("not odd"))
end

struct Even <: HasParity
    i::Int64
    Even(i::Integer) = new(iseven(i) ? i : error("not even"))
end

parity(i) = return iseven(i) ? Even(i) : Odd(i)

foo(i::Odd) = println("$i is odd.")
foo(i::Even) = println("$i is even.")


for n  in 1:4
    k::HasParity = parity(n)
    foo(k)
end
抽象类型HasParity end

struct Odd您可以使用
@生成的
函数解决此问题:

但最简单的解决方案是在代码中使用普通分支:

function foo(x::MyType{N}) where {N}
    if isodd(N)
        return _oddfoo(x)
    else
        return _evenfoo(x)
    end
end
这似乎是类型系统的失败,但如果在编译时知道
N
,编译器实际上将只选择正确的分支,并且您将获得对正确函数的静态分派,而不会损失性能


这是惯用的,据我所知,在大多数情况下推荐的解决方案。

您可以使用生成的
@函数解决此问题:

但最简单的解决方案是在代码中使用普通分支:

function foo(x::MyType{N}) where {N}
    if isodd(N)
        return _oddfoo(x)
    else
        return _evenfoo(x)
    end
end
这似乎是类型系统的失败,但如果在编译时知道
N
,编译器实际上将只选择正确的分支,并且您将获得对正确函数的静态分派,而不会损失性能


这是惯用的方法,据我所知,在大多数情况下推荐的解决方案。

据我所知,多重分派是基于类型的。你需要在函数中设置条件,而不是对这类事情使用多重分派。这个问题与最近提出的这个问题奇怪地相似:检查我的答案,我认为这比挖掘特定类型更简洁。据我所知,多重分派是基于类型的。你需要在函数中设置条件,而不是对这类事情使用多重分派。这个问题与最近提出的这个问题奇怪地相似:检查我的答案,我认为这比挖掘特定类型更简洁。你在这里描述的不是一个特征:它仅仅是一个(用户编写的)在两个实现之一上执行运行时检查调度。性状依靠类型系统实现与遗传树正交的多态形式。关于traits的介绍,请参见这个示例。您在这里描述的不是trait:它只是(用户编写的)对两个实现之一的运行时检查分派。性状依靠类型系统实现与遗传树正交的多态形式。参见本例,了解特征的介绍。