Get the enumerate type components from the string counterpart

This is a simple task. I tried the following and it did not work.

julia> @enum Fruit apple=0 pear=1 banana=2 
julia> Fruit("apple")
ERROR: MethodError: no method matching Fruit(::String)
Closest candidates are:
  Fruit(::Integer) at Enums.jl:134
Stacktrace:
 [1] top-level scope at none:0

Is there a reason to avoid the enum’s names?

julia>  @enum Fruit apple=0 pear=1

julia> apple
apple::Fruit = 0

julia> pear
pear::Fruit = 1

I have a string, say, “banana”, I’d like to change it back to the corresponding enumerate type…

without error checking

julia> function fruit(s::String)
          [apple, pear][s .== ["apple", "pear"]][1]
       end
fruit (generic function with 1 method)

julia> fruit("pear")
pear::Fruit = 1

or

function fruit(s::String)
      Fruit( (0:1)[s .== ["apple", "pear"]][1] )
end
1 Like

Good. Are there default functions that I can use directly? By the way, what is s .==?

s .== [a, b] is [s === a, s === b]
s .= [a, b] is [s == a, s == b]

Default functions for what purpose?

for transfer a string to the enumerate type counterpart

not entirely

julia> instances(Fruit)
(apple, pear)

julia> string.(instances(Fruit))
("apple", "pear")

what you did above is transferring the enumerate to string counterpart.

you can do this

const fruits = instances(Fruit)
const fruitvalues = Int32.(fruits)
const fruitstrings = string.(fruits)
fruit(s::String) = Fruit(fruitvalues[[(s .== fruitstrings)...]][1])

fruit("apple")
apple::Fruit == 0
3 Likes

I also would like this kind of functionality for all my Enums, but I don’t like declaring constants for every enum.

I’ve arrived so far on the solution below. But I should probably write my own enum macro, similar to this discussion on enum dot access:

function get_instance(enum::DataType, str::String)
	idx = findfirst(x -> x==str, instance_names(enum))
	if idx == nothing
		throw(ArgumentError("invalid value for Enum $enum: $str"))
	else
		return enum(idx-1)
	end
end
instance_names(enum::DataType) = string.(instances(enum))

@enum Fruits begin
    apple
	pear
	banana
end
Fruits(str::String) = get_instance(Fruits, str)
Base.convert(::Type{Fruits}, str::String) = Fruits(str)

Now this works fine:

julia> Fruits("banana")
banana::Fruits = 2

julia> Fruits("monkey")
ERROR: ArgumentError: invalid value for Enum Fruits: monkey

I had to add the Base.convert since I am creating an enum instance from a constructor:

struct FruitBowl
   fruit::Fruits
end

julia> bowl = FruitBowl("banana")
julia> bowl.fruit
banana::Fruits = 2

I do not know why I could not dispatch on the Enum type though. typeof(Fruits) returned Datatype, not Enum.

… because you tried taking the type of the Enum rather than the type of an instance of it:

julia> typeof(Fruits)
DataType

julia> typeof(bowl.fruit)
Enum Fruits:
apple = 0
pear = 1
banana = 2
1 Like