Многократная отправка в юли с одним и тем же типом переменной - PullRequest
1 голос
/ 15 апреля 2020

Обычно многократная отправка в julia проста, если один из параметров в функции меняет тип данных, например Float64 против Complex{Float64}. Как реализовать множественную диспетчеризацию, если параметр является целым числом, и мне нужны две функции: одна для четных, а другая для нечетных значений?

Ответы [ 4 ]

4 голосов
/ 16 апреля 2020

Вы можете решить эту проблему с помощью функции @generated: https://docs.julialang.org/en/v1/manual/metaprogramming/#Generated -functions-1

Но самое простое решение - использовать обычную ветвь в вашем коде:

function foo(x::MyType{N}) where {N}
    if isodd(N)
        return _oddfoo(x)
    else
        return _evenfoo(x)
    end
end

Это может показаться поражением для системы типов, но если во время компиляции известно N, компилятор фактически выберет only правильную ветвь, и вы получит c отправку к правильной функции без потери производительности.

Это идиоматизм c, и, насколько мне известно, рекомендуемое решение в большинстве случаев.

2 голосов
/ 16 апреля 2020

Я ожидаю, что с диспетчеризацией типа вы, в конечном счете, по-прежнему будете вызывать после проверки на нечетное и четное, поэтому наиболее экономичный код, без пенического времени выполнения, будет заставлять вызывающую программу проверять аргумент и вызывать правильный функция.

Если вы, тем не менее, должны быть основаны на типах, по некоторым причинам, не связанным с эффективностью во время выполнения, вот пример такого:

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
1 голос
/ 15 апреля 2020

Итак, вот еще один вариант, который, на мой взгляд, более чистый и ориентирован на несколько отправок (предоставленный коллегой). Давайте подумаем, что N - это проверенное натуральное число, и я хочу две функции, которые выполняют разные функции, в зависимости от того, является ли N четным или нечетным. Таким образом

boolN = rem(N,2) == 0
(...)
function f1(::Val{true}, ...)
(...)
end
function f1(::Val{false}, ...)
(...)
end

и для вызова функции достаточно просто сделать

f1(Val(boolN))
0 голосов
/ 15 апреля 2020

Как отметил @logankilpatrick, система диспетчеризации основана на типах. Однако то, что вы отправляете, - это хорошо известная модель, известная как черта характера.

По сути ваш код выглядит как

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