Reputation: 3451
Usually the multiple dispatch in julia is straightforward if one of the parameters in a function changes data type, for example Float64
vs Complex{Float64}
. How can I implement multiple dispatch if the parameter is an integer, and I want two functions, one for even and other for odd values?
Upvotes: 2
Views: 1190
Reputation: 12654
You may be able to solve this with a @generated
function: https://docs.julialang.org/en/v1/manual/metaprogramming/#Generated-functions-1
But the simplest solution is to use an ordinary branch in your code:
function foo(x::MyType{N}) where {N}
if isodd(N)
return _oddfoo(x)
else
return _evenfoo(x)
end
end
This may seem as a defeat for the type system, but if N
is known at compile-time, the compiler will actually select only the correct branch, and you will get static dispatch to the correct function, without loss of performance.
This is idiomatic, and as far as I know the recommended solution in most cases.
Upvotes: 4
Reputation: 6086
I expect that with type dispatch you ultimately still are calling after a check on odd versus even, so the most economical of code, without a run-time penatly, is going to be having the caller check the argument and call the proper function.
If you nevertheless have to be type based, for some reason unrelated to run-time efficiency, here is an example of such:
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
Upvotes: 2
Reputation: 3451
So here's other option which I think is cleaner and more multiple dispatch oriented (given by a coworker). Let's think N
is the natural number to be checked and I want two functions that do different stuff depending if N
is even or odd. Thus
boolN = rem(N,2) == 0
(...)
function f1(::Val{true}, ...)
(...)
end
function f1(::Val{false}, ...)
(...)
end
and to call the function just do
f1(Val(boolN))
Upvotes: 1
Reputation: 81
As @logankilpatrick pointed out the dispatch system is type based. What you are dispatching on, though, is well established pattern known as a trait.
Essentially your code looks like
myfunc(num) = iseven(num) ? _even_func(num) : _odd_func(num)
Upvotes: 0