The following example
@enum Tags A B C
x = [A A B C B C]
x .== A
gives me
ERROR: MethodError: no method matching length(::Tags)
The Enum.jl file should include the following functions
length(::Enum) = 1
iterate(x::Enum) = (x, nothing)
iterate(::Enum,::Nothing) = nothing
which would allow x .== A to result in the expected result
1脳6 BitArray{2}:
true true false false false false
The functions could also be defined for the subtype ::Tags via the @enum macro, if this is desirable?
julia> versioninfo()
Julia Version 1.0.0
Commit 5d4eaca0c9 (2018-08-08 20:58 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel(R) Xeon(R) CPU E5-2470 v2 @ 2.40GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-6.0.0 (ORCJIT, ivybridge)
Perhaps it makes sense to iterate an enum, but note that you can do this:
julia> @enum Tags A B C
julia> x = [A A B C B C];
julia> x .== Ref(A)
1脳6 BitArray{2}:
true true false false false false
I know @fredrikekre, but going down that road I am sure to write x == Ref(A) some day for a single element, and get invalid code that is not easily detected. Also, the x .== Ref(A) variant generates more than double the instructions if you inspect it via @code_llvm.
I don't think an Enum should be iterable so the solution would be to define Base.broadcastable to return a Ref wrapped instance of the enum.
Would you mind elaborating why not @KristofferC? I see them defined for ::Number in number.jl:
length(x::Number) = 1
iterate(x::Number) = (x, nothing)
iterate(x::Number, ::Any) = nothing
The fact that numbers are iterable has been a point of discussion (https://github.com/JuliaLang/julia/issues/7903) but Enums are not numbers so it doesn't apply here. Why do you want to iterate Enums?
Thank you for pointing me to discussion #7903. I now understand why you want enum values to be broadcastable, but not iterable. I still find it weird though to construct a new iterable object to hold the enum value. I mean Base.broadcastable(x::Enum) = Ref(x) is definitely better than Base.broadcastable(x::Enum) = [x], but I wonder if it is possible handle it purely via the type system? For example, by casting to an IterEnum type?
Using a trait for what is considered scalars w.r.t broadcasting has been discussed but, for now, the way to do it is to wrap it in a length one iterable container.
Closed by #30670
Most helpful comment
I don't think an Enum should be iterable so the solution would be to define
Base.broadcastableto return aRefwrapped instance of the enum.