Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Macro for switch or pattern matching with an Enum

Tags:

enums

julia

I would like to have some syntactic sugar for switching on an Enum. Of course, an if else block works as expected:

@enum Fruit apple=1 orange=2 kiwi=3

function talk1(fruit::Fruit)
    if fruit == apple
        "I like apples."
    elseif fruit == orange
        "I like oranges."
    else
        "I like kiwis."
    end
end

I could even do the following:

function talk2(fruit::Fruit)
    say = ["I like apples.", "I like oranges.", "I like kiwis."]
    say[Int(fruit)]
end

But I don't really like the approach in talk2, since it allocates a vector and is less readable. I tried the Match.jl package, but I can't seem to match an Enum:

using Match

function talk3(fruit::Fruit)
    @match fruit begin
        apple  => "I like apples."
        orange => "I like oranges."
        kiwi   => "I like kiwis."
    end
end
julia> talk3(apple)
"I like apples."

julia> talk3(orange)
"I like apples."

julia> talk3(kiwi)
"I like apples."

Of course, in the @match macro I could cast the Enum as an Int and match the Int, but that hampers the readability of the switch.

Is there a way to get Match.jl to work on an Enum? Or is there a macro from a different package that can switch on an Enum?

like image 801
Cameron Bieganek Avatar asked Jan 01 '23 23:01

Cameron Bieganek


1 Answers

This is perhaps the main reason to use types instead of enums. Then dispatch handles this for you:

abstract type Fruit end
struct Apple <: Fruit end
struct Orange <: Fruit end
struct Kiwi <: Fruit end

talk(fruit::Apple) = "I like apples."
talk(fruit::Orange) = "I like oranges."
talk(fruit::Fruit) = "I like kiwis."

As https://pixorblog.wordpress.com/2018/02/23/julia-dispatch-enum-vs-type-comparison/ point out, this code is efficiently inlined by the compiler.

like image 67
Ian Fiske Avatar answered Feb 20 '23 09:02

Ian Fiske