More comfortable enum?

What I would expect is, if I have an enum like:

@enum Color begin
    red
    green
    blue
end

That if I type Color. <TAB><TAB> that I get a list of colors to choose from.

But this is not the case.

Is there a way to achieve this behaviour?

GitHub - fredrikekre/EnumX.jl: This is what I wish `Base.@enum` was. is one option.

I have also just added a module with some non-instantiable types for user-facing enums where I want users to discover the types through tab, for example (untested as Im typing on phone):

module Color
  abstract type red end
  abstract type green end
  abstract type blue end
end

Not sure if there are disadvantages with the latter though.

2 Likes

What you want is basically a namespace, so, in Julia, a Module. I usually simply write a small inline module when I want an enumeration type:

"""
`Actions.Action` is an enumeration type. The allowed values are:
1. `Actions.add` for adding
2. `Actions.move` for moving
3. `Actions.finish` for finishing
"""
module Actions
  struct UnknownActionException <: Exception
    unrecognized_action::Int
  end
  struct Action
    a::Int
    function Action(a::Int)
      (0 ≤ a ≤ 2) || throw(UnknownActionException(a))
      new(a)
    end
  end
  const add = Action(0)
  const move = Action(1)
  const finish = Action(2)
  const actions = (add, move, finish)
  const compile_time_test = (
    () ->
      if allunique(actions)
        nothing
      else
        error("inconsistent enumeration definition")
      end
  )()
end

Maybe it would make more sense to just use EnumX, though.

Could you give more context on how do you use this? I suspect that using singleton structs would be more idiomatic than using abstract type.

It was just for a very simple case when I wanted some labels for the user input, the kind where it is common to see symbols. I wanted them to be tabbable and I wanted to make sure everything discoverable through tab was a valid input.

1 Like

EnumX looks like a solution (TAB completion works), but then I always need to prefix the enum values with the enum type… Not sure if I want this.

I have a function run_tests(test...) where test is a member of the enum TestCases. See:

function help()
    println("Run one or more of the following tests:\n")
    for test in instances(TestCases)
        println("run_tests($(String(Symbol(test))))")
    end
end

Not sure yet if I change anything, both enum and enumx have their advantages…

You can always define

julia> @enumx Fruit Apple Orange

julia> const Apple = Fruit.Apple

(which sort of defeats the purpose of the EnumX package, though).

1 Like

Isn’t exactly this sort of problem addressed with module import and using?
I would expect an Enum declaration to export values if it wishes, and then these would be in the namespace if the Enum is using-ed, and if I care about cluterring the namespace, then import can be used.

Can some sort of syntax/macro achieve this?

This is exactly what macro @enumx does. It do a simple Enum declaration inside a Module so it is immediately scoped.

3 Likes