# Solving the drawbacks of @enum

**URL:** <https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506>\
**Category:** New to Julia\
**Tags:** enum\
**Created:** [January 12, 2022, 7:12pm UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506 "2022-01-12T19:12:03Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)\
**Post date:** [January 12, 2022, 7:12pm UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/1 "2022-01-12T19:12:03Z")

</div>

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](https://discourse.julialang.org/t/encapsulating-enum-access-via-dot-syntax/11785) 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?

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [January 13, 2022, 2:59am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/2 "2022-01-13T02:59:57Z")

</div>

> [@taotree](#):
>
> - I need to go back and forth between strings and enums easily.

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

---

<div class="post-metadata">

**Author:** ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)\
**Post date:** [January 13, 2022, 3:35am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/3 "2022-01-13T03:35:02Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![BioTurboNick](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bioturbonick/32/6380_2.png) [@BioTurboNick](https://discourse.julialang.org/u/BioTurboNick)\
**Post date:** [January 13, 2022, 3:47am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/4 "2022-01-13T03:47:02Z")

</div>

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

Maybe this does what you need?

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

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

```

---

<div class="post-metadata">

**Author:** ![BioTurboNick](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bioturbonick/32/6380_2.png) [@BioTurboNick](https://discourse.julialang.org/u/BioTurboNick)\
**Post date:** [January 13, 2022, 3:54am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/5 "2022-01-13T03:54:29Z")

</div>

> 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?

---

<div class="post-metadata">

**Author:** ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)\
**Post date:** [January 13, 2022, 4:04am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/6 "2022-01-13T04:04:39Z")

</div>

@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.

---

<div class="post-metadata">

**Author:** ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)\
**Post date:** [January 13, 2022, 4:09am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/7 "2022-01-13T04:09:47Z")

</div>

> [@BioTurboNick](#):
>
> > I need to go back and forth between strings and enums easily.
> 
> Maybe this does what you need?
> 
> ```julia
> @enum Foo x y
> string(x)
> string(y)
> 
> eval(Symbol("x"))
> eval(Symbol("y"))
> 
> ```

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.

---

<div class="post-metadata">

**Author:** ![BioTurboNick](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bioturbonick/32/6380_2.png) [@BioTurboNick](https://discourse.julialang.org/u/BioTurboNick)\
**Post date:** [January 13, 2022, 4:59am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/8 "2022-01-13T04:59:50Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [January 13, 2022, 5:29am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/9 "2022-01-13T05:29:57Z")

</div>

> [@BioTurboNick](#):
>
> It seems like the baremodule version hits your needs, with the only downside of needing different names for the type and module.

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.

> <https://github.com/JuliaLang/julia/pull/42154>
>
> I never got around to addressing Jeff's suggestion that empty modules should no…t contain a reference to themselves.
> 
> This PR (which I wrote in March but didn't push for some reason D:) addresses that and also tweaks the interface and the docs slightly.

---

<div class="post-metadata">

**Author:** ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)\
**Post date:** [January 13, 2022, 5:35am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/10 "2022-01-13T05:35:48Z")

</div>

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: [https://github.com/kindlychung/SuperEnum.jl](https://github.com/kindlychung/SuperEnum.jl) which appears to make the bare module approach easy to do.

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [January 13, 2022, 5:37am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/11 "2022-01-13T05:37:01Z")

</div>

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

[Algebraic Data Types — MLStyle.jl Documentation](https://thautwarm.github.io/MLStyle.jl/latest/syntax/adt.html)

---

<div class="post-metadata">

**Author:** ![ultrapoci](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ultrapoci/32/25356_2.png) [@ultrapoci](https://discourse.julialang.org/u/ultrapoci)\
**Post date:** [March 24, 2022, 10:11pm UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/12 "2022-03-24T22:11:53Z")

</div>

[EnumX.jl](https://discourse.julialang.org/t/ann-enumx-jl-improved-enums-for-julia/78096) has been recently released, it might suit your needs (note that I’m not the author of the package).

---

<div class="post-metadata">

**Author:** ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)\
**Post date:** [March 26, 2022, 1:13am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/13 "2022-03-26T01:13:18Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [March 29, 2023, 4:22am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/14 "2023-03-29T04:22:43Z")

</div>

So I’ve made some updates to [SumTypes.jl](https://github.com/MasonProtter/SumTypes.jl) which I believe solves your problems posted here.

> 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.

SumTypes.jl now lets you avoid polluting the name space:

```julia
julia> using SumTypes

julia> @sum_type Fruit begin
           apple
           banana
           orange
       end hide_variants=true
Fruit

julia> apple
ERROR: UndefVarError: apple not defined

julia> Fruit'.apple # note that I used Fruit' not Fruit
apple::Fruit

julia> let (;orange, banana) = Fruit'
           orange
       end
orange::Fruit

```

* * *

> Override Base.show for enums doesn’t appear to work.

Should work fine with SumTypes:

```julia
julia> Base.show(io::IO, f::Fruit) = @cases f begin
           apple => print(io, "apple")
           banana => print(io, "banana")
           orange => print(io, "orange")
       end

julia> Fruit'.apple
apple

```

* * *

> 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 agree, so I didn’t do that.

```julia
julia> typeof(Fruit'.apple) === Fruit
true

```

* * *

> I found this online: Encapsulating enum access via dot syntax But that results in allocations just to reference MyEnum.value

Don’t have that problem here:

```julia
julia> @btime Fruit'.apple
  1.258 ns (0 allocations: 0 bytes)
apple

julia> @code_typed Fruit'.apple
CodeInfo(
1 ─ %1 = Base.getfield(x, f)::Fruit
└── return %1
) => Fruit

```

* * *

> I don’t need nor want the values in the type system, so that’s not an option.

I use values, not types:

```julia
julia> Fruit'.apple isa Type
false

```

---

<div class="post-metadata">

**Author:** ![o314](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/o314/32/252_2.png) [@o314](https://discourse.julialang.org/u/o314)\
**Post date:** [April 8, 2023, 3:24am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/15 "2023-04-08T03:24:18Z")

</div>

_This is a cross post from [https://discourse.julialang.org/t/retrieving-an-instance-of-an-enum-using-a-string/61183/7](https://discourse.julialang.org/t/retrieving-an-instance-of-an-enum-using-a-string/61183/7)_ . That may be of interest here too

```julia
@enum LogLevel begin
    LL_INFO
    LL_DEBUG
end

```

Please also note from

```julia
Base.tryparse(E::Type{<:Enum}, str::String) =
    let insts = instances(E) ,
        p = findfirst(==(Symbol(str)) ∘ Symbol, insts) ;
        p !== nothing ? insts[p] : nothing
    end

using Test
@testset "now" begin
    @test tryparse(LogLevel, "LL_INFO") == LL_INFO
    @test tryparse(LogLevel, "ll_info") == nothing
    @test tryparse(LogLevel, "INFO") == nothing
    @test tryparse(LogLevel, "info") == nothing
end

```

Those possibles evolutions :

```julia
Base.tryparse(E::Type{<:Enum}, str::String; prefix::String="") =
    let eq(x, e) = lowercase(prefix*x) == lowercase(e) ,
        # eq could be statically dispatchable according to some enum surface lang traits
        insts = instances(E) ,
        p = findfirst(insts .|> string) do e; eq(str,e) end;
        p !== nothing ? insts[p] : nothing
    end

@testset "meanwhile" begin
    @test tryparse(LogLevel, "LL_INFO") == LL_INFO
    @test tryparse(LogLevel, "ll_info") == LL_INFO
    @test tryparse(LogLevel, "INFO"; prefix="LL_") == LL_INFO
    @test tryparse(LogLevel, "info"; prefix="LL_") == LL_INFO
end

```

particulaly considering [Solving the drawbacks of @enum](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506)

---

<div class="post-metadata">

**Author:** ![RomainPct](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/romainpct/32/49995_2.png) [@RomainPct](https://discourse.julialang.org/u/RomainPct)\
**Post date:** [June 23, 2023, 8:12am UTC](https://discourse.julialang.org/t/solving-the-drawbacks-of-enum/74506/16 "2023-06-23T08:12:16Z")

</div>

[EnumX.jl](https://github.com/fredrikekre/EnumX.jl) is really cool! However, there are times when it may not be necessary to assign names to instances of the enums at all.

As an example, I’ve quickly implemented this (unregistered) package called [AnonynousEnums.jl](https://github.com/poncito/AnonymousEnums.jl). Check it out and let me know your thoughts. I’m considering registering it.

The motivation behind this package came from the challenge of generating Julia enums from capnproto schema. I wanted to make it easier for users by eliminating the need to worry about where and how the instances of the enums are defined uniquely. This approach helps keep the API as simple as possible, as users won’t have to be aware of the generated types. Additionally, I prefer treating this as an implementation detail that I’m free to modify in the future.

Edit: just did a PR on the General Registry
