user2820579
user2820579

Reputation: 3451

Multiple dispatch in julia with the same variable type

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

Answers (4)

DNF
DNF

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

Bill
Bill

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

user2820579
user2820579

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

Miles Lucas
Miles Lucas

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

Related Questions