This has been posed, sort of, several times in Discourse or stackoverflow.
For this example: @enum condition nil=5 mild sick severe
It is easy to get the enum with an integer:
julia> condition(5)
nil::condition = 5
I have a need to convert a string that matches the enum’s appearance to the actual enum: to go from “nil” to nil::condition = 5
.
Here are 2 versions of strtoenum
. Which of these would be preferred?
First, using the function Base.Enums.namemap, which is not exported.
function strtoenum(enumgrp::Type{<:Enum{T}}, str::String) where {T<:Integer}
dict = Base.Enums.namemap(enumgrp)
found = -1
srch = Symbol(str)
for (k,v) in dict
if v == srch
found = k
break
end
end
if found != -1
return enumgrp(found)
end
end
julia> @btime strtoenum(condition, "nil")
68.191 ns (0 allocations: 0 bytes)
nil::condition = 5
Second, using instances, which is documented, rather than namemap:
function strtoenum2(enumgrp::Type{<:Enum{T}}, str::String) where {T<:Integer}
srch = Symbol(str)
found = -1
for val in instances(enumgrp)
if srch == Symbol(val)
found = val
break
end
end
if found != -1
return found
end
end
julia> @btime strtoenum2(condition, "nil")
71.731 ns (0 allocations: 0 bytes)
nil::condition = 5
Break-even in performance; no allocations.
Questions:
- Neither raises an error if the input string doesn’t match the name of the enum–instead returning nothing. Should a value error be raised? nothing is probably going to cause an error if you try to use the return value for anything.
- Which is preferred?
- Is this worth a PR to enum? It’s way slower than
condition(5)
, which has nothing to do. The cost is linear in the number of instances in the enum set.