Stream: helpdesk (published)

Topic: ∈ (item, e::Enum)


view this post on Zulip Peter Goodall (Nov 30 2021 at 02:51):

Is this wrong-thinking?

import Base.∈
(item, e::Enum) =  item  elements(e)
  1. I want to write code to check if an operation on members of the enumeration is closed within the Enum.
  2. This implies iteration over members of an Enum. It would have been more complete to implement an iterate() instead. Is it bad type-thinking to enumerate an Enum? Sort of makes sense.

view this post on Zulip Peter Goodall (Nov 30 2021 at 03:19):

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)

view this post on Zulip Andrés Riedemann (Nov 30 2021 at 04:25):

sorry, i dont understand the question, do you have a situation where item is not an enum?

view this post on Zulip Andrés Riedemann (Nov 30 2021 at 04:25):

are you comparing by numerical value?

view this post on Zulip Andrés Riedemann (Nov 30 2021 at 04:32):

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

view this post on Zulip Andrés Riedemann (Nov 30 2021 at 04:40):

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))

view this post on Zulip Sukera (Nov 30 2021 at 07:32):

when you define a new enum with @enum <Name> <instances...>, you define a new type called <Name>, which subtypes Enum

view this post on Zulip Sukera (Nov 30 2021 at 07:34):

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

view this post on Zulip Sukera (Nov 30 2021 at 07:35):

for more info, check ?@enum

view this post on Zulip Sukera (Nov 30 2021 at 07:36):

to get all valid instances of an enum, you can use instances(Fruits)

view this post on Zulip Peter Goodall (Nov 30 2021 at 20:44):

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 Enumgiven 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.

view this post on Zulip Sukera (Nov 30 2021 at 20:45):

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

view this post on Zulip Sukera (Nov 30 2021 at 20:46):

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)

view this post on Zulip Sukera (Nov 30 2021 at 20:46):

that's also why there's no default definition for Enum - there is no generally applicable iterate function that would work for all Enums

view this post on Zulip Sukera (Nov 30 2021 at 20:48):

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

view this post on Zulip Peter Goodall (Nov 30 2021 at 22:06):

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

view this post on Zulip Sukera (Nov 30 2021 at 22:08):

well can you give me a universal definition for any given Enum on how to iterate over it or its instances?

view this post on Zulip Sukera (Nov 30 2021 at 22:10):

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.

view this post on Zulip Sukera (Nov 30 2021 at 22:14):

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).

view this post on Zulip Sukera (Nov 30 2021 at 22:16):

To be clear, Enum in julia is the same conceptually as an enumerated type, not an enumeration.

view this post on Zulip Sukera (Nov 30 2021 at 22:18):

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.

view this post on Zulip Peter Goodall (Nov 30 2021 at 22:42):

@Sukera

@enum 𝔹 ᛰ ᛯ

for i ∈ instances(𝔹)
@show i
end

view this post on Zulip Sukera (Nov 30 2021 at 22:45):

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.

view this post on Zulip Peter Goodall (Nov 30 2021 at 22:58):

@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

view this post on Zulip Mason Protter (Nov 30 2021 at 23:19):

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

view this post on Zulip Mason Protter (Nov 30 2021 at 23:21):

Similarly,

julia> 1 isa Int
true

julia> 1  Int
ERROR: MethodError: no method matching iterate(::Type{Int64})

view this post on Zulip Sukera (Nov 30 2021 at 23:25):

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

view this post on Zulip Mason Protter (Nov 30 2021 at 23:26):

I guess I'm sympathetic to the idea of thinking of types as collections

view this post on Zulip Mason Protter (Nov 30 2021 at 23:26):

Though as I said, such thinking is not idiomatic in julia

view this post on Zulip Sukera (Nov 30 2021 at 23:27):

For me to subscribe to that notion would require proper dependent typing, which we don't have in general :shrug:


Last updated: Oct 02 2023 at 04:34 UTC