# \[ANN\] AnonymousEnums.jl

**URL:** https://discourse.julialang.org/t/ann-anonymousenums-jl/100903
**Category:** Package Announcements
**Created:** [June 27, 2023, 5:02pm UTC](https://discourse.julialang.org/t/ann-anonymousenums-jl/100903 "2023-06-27T17:02:38Z")
**Posts on this page:** 7
**Page:** 1

<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 27, 2023, 5:02pm UTC](https://discourse.julialang.org/t/ann-anonymousenums-jl/100903/1 "2023-06-27T17:02:38Z")

</div>

Hi there,

I’d like to introduce you to [AnonymousEnums.jl](https://github.com/poncito/AnonymousEnums.jl), a package designed to simplify enum definitions.

AnonymousEnums.jl offers a solution to the challenge of assigning unique names to each instance of an enum subtype. Unlike other packages like [Enumx.jl](https://github.com/fredrikekre/EnumX.jl), which places enums in modules (to ensure uniqueness), AnonymousEnums.jl takes a different approach. It allows you to define instances without setting unique names for the instances. You can use symbols to set a value and test for equality:

```julia
julia> @anonymousenum Fruit::UInt8 begin
           apple
           banana
       end
julia> apple = Fruit(:apple)
julia> @assert apple == Fruit(0)
julia> @assert apple == :apple
julia> @assert instances(Fruit) == (:apple, :banana)

```

This package is particularly useful for _typed code generation_ scenarios. I am personnaly using this for capnproto code generation. It enables me to keep the (qualified) names of enum instances hidden as implementation details, eliminating the need for users to know them.

It allows me to provide a more user-friendly interface, like this:

```julia
julia> writer.fruit.type = :apple
julia> if reader.fruit.type == :apple
           # do something
       elseif reader.fruit.type == :banana
           # do something else
       end

```

instead of:

```julia
julia> writer.fruit.type = GeneratedNameForThisEnum.apple
julia> if reader.fruit.type == GeneratedNameForThisEnum.apple
           # do something
       elseif reader.fruit.type == GeneratedNameForThisEnum.banana
           # do something else
       end

```

Now, I want to address a potential concern. Although I initially had reservations about confusing symbols with instances of enums, I found that it was better to use `apple == :apple` instead of `AnonymousEnums.isequal(apple, :apple)`. However, I understand that this choice may introduce some confusion. If you have any suggestions or alternative approaches, I’m interested in hearing them.

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [June 27, 2023, 5:18pm UTC](https://discourse.julialang.org/t/ann-anonymousenums-jl/100903/2 "2023-06-27T17:18:12Z")

</div>

IMO it would be much nicer if you added a new function to your package instead of overloading `Base.:(==)`.

Note that the user can always set a convenient shorthand version for your function, like:

```julia
const f = AnonymousEnums.long_function_name

```

---

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [June 27, 2023, 6:26pm UTC](https://discourse.julialang.org/t/ann-anonymousenums-jl/100903/3 "2023-06-27T18:26:48Z")

</div>

Or you might be able to find an infix Unicode operator that makes sense.

---

<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 30, 2023, 1:08pm UTC](https://discourse.julialang.org/t/ann-anonymousenums-jl/100903/4 "2023-06-30T13:08:01Z")

</div>

Thank you for your feedback.

I have considered @nsajko’s suggestion and will implement it, allowing users to remap it according to their preferences.

While the Unicode operator offers elegance, it may not be universally appreciated. Personally, I don’t mind its usage. However, developers with visual impairments, those using older text editors (as I have heard), or individuals transitioning from other programming languages may prefer the first solution.

---

<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 30, 2023, 1:15pm UTC](https://discourse.julialang.org/t/ann-anonymousenums-jl/100903/5 "2023-06-30T13:15:49Z")

</div>

Actually… What would you think of using `Base.isequal`?  
It is used [here](https://github.com/JuliaLang/julia/blob/master/stdlib/Dates/src/periods.jl#L348) to compare a `CompoundPeriod` with a `Period`, by calling the constructor of `CompoundPeriod` on the `Period` object. Which is kind of what I’m doing (CompoundPeriod → Enum and Period → Symbol).

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [June 30, 2023, 1:53pm UTC](https://discourse.julialang.org/t/ann-anonymousenums-jl/100903/6 "2023-06-30T13:53:36Z")

</div>

> [@RomainPct](#):
>
> What would you think of using `Base.isequal`?

The core issue is that both `isequal` and `==` have established semantics that are different than what you define in your methods. This can lead to confusion, and, in the case of `isequal`, the bigger problem is the interfaces that must be respected, see documentation [entry](https://docs.julialang.org/en/v1/base/base/#Base.isequal). The TLDR is that `isequal` is used by `Dict` (and perhaps similar user-defined types) for comparisons, which is _not_ what you want, I’m pretty sure. If it _is_ what you want, then you have to define `isless` and `hash` (and `<`, I think) consistently.

Have you considered Cameron Bieganek’s suggestion? Here’s the relevant documentation (a bit incomplete, though): [entry](https://docs.julialang.org/en/v1/base/math/#Customizable-binary-operators).

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [June 30, 2023, 1:59pm UTC](https://discourse.julialang.org/t/ann-anonymousenums-jl/100903/7 "2023-06-30T13:59:40Z")

</div>

> [@nsajko](#):
>
> Have you considered Cameron Bieganek’s suggestion? Here’s the relevant documentation (a bit incomplete, though): [entry](https://docs.julialang.org/en/v1/base/math/#Customizable-binary-operators).

Maybe you could use one of the arrow symbol pairs:

> <https://github.com/JuliaLang/julia/blob/ad939df098a58f38c6a2dc9aec5976f098a5e5e5/src/julia-parser.scm#L13>

For example, `←` for one method, and `→` for its opposite.

But you may also want to make sure that whatever symbols you pick are supported by the unicode autocompletion in the REPL and editors.

EDIT: sorry, I wasn’t clear at all. What I meant is that you have two options, you could pick a symmetric-looking symbol and then give it two methods (similarly to the code you have now), like so:

```julia
↔(s::Symbol, x::AnonymousEnum) = x ↔ s
↔(x::T, s::Symbol) where {T <: AnonymousEnum} = x == T(s)

```

_Or_ you could pick _two_ opposite-looking symbols and then give a method to each one, like so:

```julia
←(s::Symbol, x::AnonymousEnum) = x → s
→(x::T, s::Symbol) where {T <: AnonymousEnum} = x == T(s)

```

The symbols I chose are just examples.

Another note: if you’re going to pick an operator instead of just a function, it’d be good to consider what precedence level would be most fit for the purpose (each symbol seems to belong to a fixed precedence level).
