Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enum.jl is missing broadcasting functions #28842

Closed
HFriberg opened this issue Aug 23, 2018 · 8 comments
Closed

Enum.jl is missing broadcasting functions #28842

HFriberg opened this issue Aug 23, 2018 · 8 comments

Comments

@HFriberg
Copy link

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)
@fredrikekre
Copy link
Member

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

@HFriberg
Copy link
Author

HFriberg commented Aug 23, 2018

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.

@KristofferC
Copy link
Member

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.

@HFriberg
Copy link
Author

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

@KristofferC
Copy link
Member

The fact that numbers are iterable has been a point of discussion (#7903) but Enums are not numbers so it doesn't apply here. Why do you want to iterate Enums?

@HFriberg
Copy link
Author

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?

@KristofferC
Copy link
Member

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.

@HFriberg
Copy link
Author

Closed by #30670

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants