Is this wrong-thinking?
import Base.∈
∈(item, e::Enum) = item ∈ elements(e)
I just failed to understand how to build an iterator. The few tutorials seem to have the same example - I exaggerate slightly... I thought I'd be able to delegate to elements(e::Enum)
sorry, i dont understand the question, do you have a situation where item is not an enum?
are you comparing by numerical value?
if that is the case, this would help:
julia> @enum h h1 h2 h3
julia> h
Enum h:
h1 = 0
h2 = 1
h3 = 2
julia> instances(h)
(h1, h2, h3) #of type Enum
oh, i found this:
Base.Enums.namemap(h)
0 => :h1
2 => :h3
1 => :h2
so if you are comparing with an integer, you could do:
import Base.∈
∈(item::Integer, e::Type{<:Enum}) = item ∈ keys(Base.Enums.namemap(e))
when you define a new enum with @enum <Name> <instances...>
, you define a new type called <Name>
, which subtypes Enum
you can construct instances of that enum like any other type and it will check whether that value is valid for this enum:
julia> @enum Fruits apple banana
julia> Fruits(1)
banana::Fruits = 1
julia> Fruits(1) === banana
true
julia> Fruits(0) === apple
true
julia> Fruits(2)
ERROR: ArgumentError: invalid value for Enum Fruits: 2
Stacktrace:
[1] enum_argument_error(typename::Symbol, x::Int64)
@ Base.Enums ./Enums.jl:85
[2] Fruits(x::Int64)
@ Main ./Enums.jl:198
[3] top-level scope
@ REPL[5]:1
for more info, check ?@enum
to get all valid instances of an enum, you can use instances(Fruits)
My apologies if I wasn't clear.
Given a reasonable definition of enumeration. What is an enumeration if not enumerable, and therefore iterable? Which I argue should be true for Enum
given the existence of instances(e::Enum)
I'm actually trying to understand why semantically I can't do the following directly.
function allPermutations(xs, n)
vec(map(collect, Iterators.product(ntuple(_ -> xs, n)...)))
end
@enum Suit ♣ ♦ ♥ ♠
for i ∈ Suit
@show i
end
for (a,b,c,d) ∈ allPermutations(Suite,4)
@show a, b, c ,d
end
I'm not sure is this is because of a missing iterate interface on Enum
, or it could be a result of language architecture at the boundary between types and instances.
enumerable just means that there's a finite number of things and you can give a unique number to it - it does not imply that it's iterable
iterable means that you have a state and a transition function to a new state - an enumeration is only the state, not the transition function (though you're free to define one for your T <: Enum
)
that's also why there's no default definition for Enum
- there is no generally applicable iterate
function that would work for all Enum
s
if you're looking for a collection of all possible values of an enum, you're looking for the instances
function, which returns a tuple of all instances of that enum which you in turn can iterate over
So what other types which can be enumerated aren't iterated over in-practice? Why wouldn't you want to?
I'm new to Julia, and environments I've worked in this stuff is very uniform. So I'm not so interested in "julia does it this way now", as what are the arguments not to? That way I hope to learn something
well can you give me a universal definition for any given Enum
on how to iterate over it or its instances?
I mean, even the wikipedia article you've cited doesn't impose iteration as a requirement for enumeration. It even goes a step further and explicitly says that it depends on the context the word is used in.
I don't know your background, but when I encountered enums in the past, it was always about having a finite set of elements as part of that enum that was important. Sure you can sort of say that a type is the set of all values embodied by that type, but that doesn't mean that any given type is an enum (or iterable, for that).
To be clear, Enum
in julia is the same conceptually as an enumerated type, not an enumeration.
The difference being that each individual instance of the enum (i.e. element of the set of values comprising the enum) has a name to it as well, which you don't have in general for types.
@Sukera
@enum 𝔹 ᛰ ᛯ
for i ∈ instances(𝔹)
@show i
end
right, and by using instances
you've opted into the arbitrary order it gives. You're still free to implement a different one for iterate
, which can give you any order you see fit.
@Sukera I'm not wanting an altercation. I'm just trying to understand some stuff. I'm also not saying any other environment is better. I'm border-line dyslexic and writing this stuff is painful... Also AFAIK wikipedia is just a starting point...
Why do you need a specific order to iterate or enumerate?
julia> for i in Set([1,2,3,4])
@show i
end
i = 4
i = 2
i = 3
i = 1
Enum seems to have a default order
julia> ᛰ < ᛯ
true
I don't think there's anything particularly wrong about wanting to use in
for this, but keep in mind that 𝔹
is a type here, and ᛰ
and ᛯ
are instances of that type, so the more julian expression of this idea is to use isa
.
julia> @enum 𝔹 ᛰ ᛯ
julia> 𝔹 isa Type
true
julia> ᛰ isa 𝔹
true
julia> ᛯ isa 𝔹
true
julia> ᛯ isa Int
false
Similarly,
julia> 1 isa Int
true
julia> 1 ∈ Int
ERROR: MethodError: no method matching iterate(::Type{Int64})
I'm opposed precisely because it's a type, not a collection - conflating the notion between a type and a value is going to make things more confusing
I guess I'm sympathetic to the idea of thinking of types as collections
Though as I said, such thinking is not idiomatic in julia
For me to subscribe to that notion would require proper dependent typing, which we don't have in general :shrug:
I originally asked for help to understand whether the way I was approaching this was ‘wrong-thinking’ including the context of types and values. I thought that maybe this was conceptually and idiomatically tricky because it’s on a semantic (whatever that means) boundary between types and values. I have my answer - many thanks to all.
Peter Goodall has marked this topic as resolved.
Last updated: Nov 06 2024 at 04:40 UTC