Is there a way to get something like this working ...
# getting-started
c
Is there a way to get something like this working to go from a string to an enum?
val banana = Type.getEnumFor("one")
Copy code
enum class Type(val stringly: String) {
    A("one"),
    B("two"),
    C("three")
}
and so banana would be == Type.A?
p
e
Copy code
Type.valueOf("one")
enumValueOf<Type>("one")
built-in
oh that's by enum entry name... yeah if you want your own you need to build your own
c
Interesting... so if my names line up 1:1 then I cannnn have it work? hm
e
Copy code
val valuesByStringly = values.associateBy { it.stringly }
valuesByStringly["one"]
2
yes
p
and, yeah, you probably want to cache the associative map instead of calling
values()
(iterates a new array each time) and iterating the list in practice unless this is called in a really hot loop it’s likely not going to matter much but it’s still good practice I think kotlin 1.9 or 2.0 is supposed to have an alternate method that doesn’t create the new array for values() each time
a
Yes, it's
entries
static property
e
in practice a linear search over a cached array is probably faster than a HashMap for 3 elements
👍 1
1
you'll have to benchmark for yourself to see where the crossover point is, if you care about that…
c
Alright. my names actually do line up (or more so... im fine with changing my enum names to lineup) so maybe I'll see if I can get away with this
Copy code
try {
    RollerToaster.Type.valueOf(this.input.type.toUppercase())
} catch (e: IllegalArgumentException) {
    Type.UNKNOWN
}
although detekt doesn't like that for some reason. hrm
Detekt - SwallowedException: The caught exception is swallowed. The original exception could be lost.
e
https://github.com/Kotlin/KEEP/blob/master/proposals/enum-entries.md
All further potential extensions, such as
valueOfOrNull(String)
,
hasValue(String)
can be implemented on the standard library level as members or extensions over
EnumEntries
.
should get better in the future
❤️ 1
c
learned something new. thanks all. if it helps. im just trying to deserialize a string from my backend to an enum of known types. I think I'm just going to go the valueOf route and stick to the names from my backend instead of trying to rename them.
m
You could shorten your try/catch above, and perhaps shut up Detekt, with this:
Copy code
runCatching {
  RollerToaster.Type.valueOf(...)
}.getOrElse(Type.UNKNOWN)
e
runCatching
is the wrong solution. if there's a
ExceptionInInitializerError
(for example) that should be propagated
m
But what If I don't want to propagate the exception and just swallow it in favour of a default value? Isn't it acceptable in that case?
e
if you get an
ExceptionInInitializerError
, your whole enum class is broken and none of its values will work. there is zero reason to swallow it and allow execution to continue.
1
the use cases for
runCatching
are meant to allow you to capture exceptions for later handling, not to drop them. https://github.com/Kotlin/KEEP/blob/master/proposals/stdlib/result.md#use-cases
115 Views