# Creating custom type of enumerations of symbols

Is it possible in julia to create a named-type that is an enumeration of symbol values?

for example a type named `Mode` that constists solely of symbols `:a`, `:b`, and `c` for example.

I tried constructing it with `Val` and `Union` but failed with type conversion errors.

Is this the sort of thing you are talking about?

``````julia> struct fun{a,b,c} end

julia> fun{:a,:b,:c}()
fun{:a,:b,:c}()

julia> typeof(ans)
fun{:a,:b,:c}

julia> f(::fun{a,b,c}) where {a,b,c} = (a,b,c)
f (generic function with 1 method)

julia> f(fun{:a,:b,:c}())
(:a, :b, :c)
``````

`@enum someenumtype A B C`
`A`

No - I want a typed symbol that contains only specific symbols ā not any symbol

A B and C arenāt symbols - I.e. :a

That is what my example in fact does. `fun{:a,:b,:c}()` is an instance of the `fun{:a,:b,:c}` type, which specifically has `:a` and `:b` and `:c` in its type, not any symbols.

``````julia> typeof(fun{:a,:b,:c}()) == typeof(fun{:x,:y,:z}())
false
``````

This example shows that the types are indeed considered different if the symbols change.

Maybe:

``````struct ConstrainedSymbol{T}
a::Symbol

ConstrainedSymbol(a) = ConstrainedSymbol{Any}(a)
ConstrainedSymbol{Any}(a) = new{Any}(a)
ConstrainedSymbol{T}(a) where {T} = a in T ? new{T}(a) : throw("Symbol :\$a is not in the supported set of symbols \$T.")
end
Base.convert(::Type{Symbol}, s::ConstrainedSymbol) = s.a
Base.Symbol(s::ConstrainedSymbol) = s.a
``````
``````julia> s = ConstrainedSymbol{(:a, :b)}(:a)
ConstrainedSymbol{(:a, :b)}(:a)

julia> s = ConstrainedSymbol{(:a, :b)}(:b)
ConstrainedSymbol{(:a, :b)}(:b)

julia> s = ConstrainedSymbol{(:a, :b)}(:c)
ERROR: "Symbol :c is not in the supported set of symbols (:a, :b)."
Stacktrace:
[1] ConstrainedSymbol{(:a, :b)}(::Symbol) at .\REPL[1]:6
[2] top-level scope at none:0

julia> s = ConstrainedSymbol(:c)
ConstrainedSymbol{Any}(:c)

julia> Symbol(s)
:c
``````
2 Likes

Doesnāt that look exceeding overly complicated to me and a type with fixed symbols???

It seems you have a specific idea in mind. If you can post your attempt, perhaps people can guide you better along your line of thought.

2 Likes

It is not currently possible to define a subtype of `Symbol` which only includes some symbols, although the idea has been proposed as a more convenient alternative to the current enum implementation.

1 Like

Thank you. I hope that they do. Without a type-safe symbol subtype the runtime errors are unavoidable.

Julia only checks types at runtimeā¦

3 Likes

As pointed out above, Julia is not type safe in that way anyway. What is your use case? There is probably a better (more Julian) way to do what youāre trying to do. For example, instead of passing around a `mode` argument that is either `:a`, `:b` or `:c` and then have different functionality depending on that mode, itād probably be cleaner to pass around functions directly, or structs that contain this functionality.

1 Like

far enough - For example, assume a function circle(p1, p2, p3, ā¦ pn, mode::ModeType) where p1 - pn are parameters and ModeType is ideally just an enumeration of :fill or :outline

the user would call the function circle(p1, p2, ā¦. pn, :fill)

all of the parameters are typed (i.e. p1::P1Type) ensuring that they are checked at runtime. The idea is to limit the mode parameter to the two symbols :fill and :outline - and not for example a misspelled symbol or any other symbol for that matter.

Does this really not work for your application?

``````julia> struct Mode{s} end

julia> function circle(args,::Mode{s}) where s
(args,s ā [:fill,:outline] ? s : throw(error("wrong Mode, \$s")))
end
circle (generic function with 1 method)

julia> circle("stuff",Mode{:fill}())
("stuff", :fill)

julia> circle("stuff",Mode{:filler}())
ERROR: wrong Mode, filler
Stacktrace:
[1] circle(::String, ::Mode{:filler}) at ./REPL[20]:1
[2] top-level scope at none:0
``````

the `circle` method specializes on the `Mode` type parameter, `:fill`. I believe, this should be able to do it.

thatās the best solution Iāve seen yet. Iād accept that as a readable solution.

Hereās another alternative:

``````julia> @enum Mode fill outline

julia> circle(3.14, outline)
3.14 - outline

julia> circle(3.14, dashed)
ERROR: UndefVarError: dashed not defined

julia> instances(Mode)
(fill::Mode = 0, outline::Mode = 1)
``````

yes, but the limitation with this alternative is readability - itās not instantly clear that āoutlineā is a symbol and not a variableā¦ thatā why I like the explicit :symbol in the construction.

1 Like

Is this idea still active in discusion? I would like it very much

Hasnāt been implemented, no, nor designed really.