# Enums with multiple non Integer values

**URL:** <https://discourse.julialang.org/t/enums-with-multiple-non-integer-values/54415>\
**Category:** New to Julia\
**Created:** [February 1, 2021, 8:38pm UTC](https://discourse.julialang.org/t/enums-with-multiple-non-integer-values/54415 "2021-02-01T20:38:32Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![xor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor/32/21782_2.png) [@xor](https://discourse.julialang.org/u/xor)\
**Post date:** [February 1, 2021, 8:38pm UTC](https://discourse.julialang.org/t/enums-with-multiple-non-integer-values/54415/1 "2021-02-01T20:38:32Z")

</div>

I am looking to reproduce enumerated value type such as available in Java and Kotlin. The values are singletons and play nicely as keys in dictionaries. A text book (Java) example looks like this:

```java
    public enum Planet {
        MERCURY(3.303e+23, 2.4397e6),
        EARTH(5.976e+24, 6.37814e6),
        // ...
        final double mass; // in kilograms
        final double radius; // in meters

        Planet(double mass, double radius) { this.mass = mass;this.radius = radius; }
    }
    
    public static void main(String[] args) {
        System.out.println(Planet.MERCURY); // MERCURY
        System.out.println(Planet.EARTH.radius); // 6378140.0
    }

```

What is a Julia idiomatic way to produce something similar?

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [February 1, 2021, 8:43pm UTC](https://discourse.julialang.org/t/enums-with-multiple-non-integer-values/54415/2 "2021-02-01T20:43:03Z")

</div>

How about

```julia
struct Planet
    mass::Float64
    radius=Float64
end
const MERCURY = Planet(3.303e+23, 2.4397e6)
...

```

---

<div class="post-metadata">

**Author:** ![xor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor/32/21782_2.png) [@xor](https://discourse.julialang.org/u/xor)\
**Post date:** [February 1, 2021, 8:49pm UTC](https://discourse.julialang.org/t/enums-with-multiple-non-integer-values/54415/3 "2021-02-01T20:49:54Z")

</div>

I suppose that for use in sets or dictionaries, I will need to implement `isequal` and `hash`. Also how would I restrict users from creating additional planets (say we are interested only in our solar system)?

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [February 1, 2021, 8:54pm UTC](https://discourse.julialang.org/t/enums-with-multiple-non-integer-values/54415/4 "2021-02-01T20:54:26Z")

</div>

You can use [`@auto_hash_equals`](https://github.com/andrewcooke/AutoHashEquals.jl) to automatically generate `hash` and `isequal` for you.

Why would you go out of your way to forbid users from creating additional planets? If the code will have assumptions broken by arbitrary planets just document this information.

---

<div class="post-metadata">

**Author:** ![xor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor/32/21782_2.png) [@xor](https://discourse.julialang.org/u/xor)\
**Post date:** [February 1, 2021, 9:00pm UTC](https://discourse.julialang.org/t/enums-with-multiple-non-integer-values/54415/5 "2021-02-01T21:00:33Z")

</div>

Thanks for the macro tip. As to documenting, I’d rather have the type system do the work instead.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [February 1, 2021, 9:29pm UTC](https://discourse.julialang.org/t/enums-with-multiple-non-integer-values/54415/6 "2021-02-01T21:29:47Z")

</div>

> [@xor](#):
>
> I’d rather have the type system do the work instead.

Well, the problem is: this solution has nothing to do with the type system (except by the fact you have a type named `Planet`). The `MERCURY` name is just the name of a `global const` binding inside your module. It is indistinguishable to the type system from any other `Planet`s objects you may instance. What you can do is to keep a `const global Set` of `Planet`s with the limited set of instances that you want to restrict the users to, and `@assert` the arguments of each function are in this `Set`.

A solution that would use the type system would be:

```julia
const MERCURY = Val(:Mercury)

mass(::Val{:Mercury}) = 3.303e+23
radius(::Val{:Mercury}) = 2.4397e6

```

This by itself does not prevent new planets being created (because the `mass` and `radius` function can be extended), but then you can create a type like:

```julia
const SolarSystemPlanet = Union{Val{:Mercury}, Val{:Venus}, #=every other planet here=#}

```

and use this type to restrict the parameters of your functions:

```julia
unwrap(::Val{T}) where {T} = T

function my_function(planet :: SolarSystemPlanet)
    println(unwrap(planet))
end

```

But this will have impacts on compilation latency (i.e., each function taking a `SolarSystemPlanet` will be specialized for each different planet it may receive). An way to avoid it is the [`@nospecialize`](https://docs.julialang.org/en/v1/base/base/#Base.@nospecialize) macro.

---

<div class="post-metadata">

**Author:** ![xor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor/32/21782_2.png) [@xor](https://discourse.julialang.org/u/xor)\
**Post date:** [February 7, 2021, 1:17pm UTC](https://discourse.julialang.org/t/enums-with-multiple-non-integer-values/54415/7 "2021-02-07T13:17:33Z")

</div>

Feels like fighting the system too much, I’ll try to model problem in a different way.
