Solving the drawbacks of @enum

So, @enum is causing me major problems:

  • I can’t use the names I want to use because it puts the names directly in the namespace. I need to go back and forth between strings and enums easily.
  • Override Base.show for enums doesn’t appear to work.
  • I don’t want to put it in a little module by itself to namespace it because I can’t use that same name for both the module and the enum which causes confusion that I have to use X for type but Y.z for values.
  • I found this online: Encapsulating enum access via dot syntax But that results in allocations just to reference MyEnum.value
  • I don’t need nor want the values in the type system, so that’s not an option.

Is there a good solution for enums that I’m missing?

1 Like

Can you explain this more? How are strings related to enums?

In this particular case, the enums match up with sets of values going to/from an external system as strings in JSON.

I was using that @scopedenum solution I linked to for a little while, but then ran into it contributing to a performance issue because I had to run various logic/calculations some millions of times.

I need to go back and forth between strings and enums easily.

Maybe this does what you need?

@enum Foo x y
string(x)
string(y)

eval(Symbol("x"))
eval(Symbol("y"))

I was using that @scopedenum solution I linked to for a little while, but then ran into it contributing to a performance issue because I had to run various logic/calculations some millions of times.

This seems surprising because they should just be treated like constants, no? Have you posted about this performance issue elsewhere?

@enum’s are just numeric constants, but the @scopedenum macro does some magic with a struct inside a module, so apparently something is going on. I just ran into it yesterday and haven’t reported it anywhere.

Right, there are solutions for that. However, the problem is the other bullet points and I have two enum’s that have the same value: EnumA x and EnumB x and need to use them both in the same code, but because enum’s aren’t namespaced, you can’t. It’s that I kept trying different solutions to make enum’s work and every time I tried something else I ran into another problem such that it wouldn’t work.

It seems like the baremodule version hits your needs, with the only downside of needing different names for the type and module. But that seems minor? Or am I missing something?

You can make a module without a reference to itself in Julia 1.8, which might let you make a type named M in a module named M.

2 Likes

As for how minor it is, depends on how you look at it. Code needs to be as readable as possible for maintenance, but… conventions are required to be known in some cases, apparently this is one of those situations.

I was asking this question in case there was new information that solves all these issues that I hadn’t found yet but was known by the community (I’m new here). But, I think you’re right, the baremodule approach seems to resolve the most number of issues. And… I just now stumbled across this: GitHub - kindlychung/SuperEnum.jl: Julia enum made nicer which appears to make the bare module approach easy to do.

1 Like

There is also an enum in MLStyle, but it uses the type domain iirc.

Algebraic Data Types — MLStyle.jl Documentation

EnumX.jl has been recently released, it might suit your needs (note that I’m not the author of the package).

Thanks. I did see that announcement, though I notice it doesn’t solve the third bullet point: The namespace and the type name are different: MyEnum vs. MyEnum.T. I understand that might be impossible to solve, though, so it looks nice. I’ll give it a try. As for what it does above SuperEnum, the EnumX README says SuperEnum “doesn’t give you Base.Enum s” though I’m don’t know the ramifications of that.