KEEP icon indicating copy to clipboard operation
KEEP copied to clipboard

Provide modern and performant replacement for Enum.values()

Open qwwdfsad opened this issue 3 years ago • 6 comments

This proposal describes a rationale and a path to migrate from function values() provided by each enum type to a collection-based and more predictable abstraction.

Text: https://github.com/Kotlin/KEEP/pull/284/files

qwwdfsad avatar Dec 13 '21 17:12 qwwdfsad

Nice! Why do you propose EnumEntriesList(Supplier) indirection? It's simpler to create a two-in-one implementation of Collections.unmodifiableList(Arrays.asList()) and pass values array directly to its constructor.

Miha-x64 avatar Jul 12 '22 20:07 Miha-x64

The separate type is useful for potential future additions on a standard library level instead of a language one. E.g. we can potentially extend EnumEntries to have such members as valueOfOrNull, valueOf(ignoreCase=true) and so on.

The main reason to inject supplier is to provide lazy instantiation to be compatible with enums that are being reflectively modified

qwwdfsad avatar Jul 13 '22 10:07 qwwdfsad

E.g. we can potentially extend EnumEntries to have such members as valueOfOrNull, valueOf(ignoreCase=true) and so on.

@qwwdfsad I'm still not sure that a separate EnumEntriesList public type makes sense for this purpose. I doubt that we will ever add valueOfOrNull or valueOf(ignoreCase=true) API to EnumEntriesList. Not only it looks ugly SomeEnum.values().valueOfOrNull("Foo"), but it's also easily replaceable with List API: SomeEnum.values().firstOrNull { it.name == "Foo" }

If we will ever want to add valueOfOrNull API then unfortunately it only makes sense as a language feature: SomeEnum.valueOfOrNull("Foo")

Right now because of the EnumEntriesList API we require the OptIn which might lower the feature adoption in the preview

nikitabobko avatar Dec 20 '22 12:12 nikitabobko

@nikitabobko First, it would be SomeEnum.entries.valueOfOrNull("Foo"). Second, it would be more efficient than linear search with firstOrNull.

ilya-g avatar Dec 20 '22 13:12 ilya-g

It appears that a reified enumEntries() function wasn't added to the stlib but was called out as planned in the KEEP here: https://github.com/Kotlin/KEEP/blob/master/proposals/enum-entries.md#collateral-changes. Was this an accidental omission or an intentional change?

The reason I ask is that while most cases can just use Enum.entries, we have a helper function like this that isn't possible without a reified API.

/** Returns an enum entry with the specified name or `null` if no such entry was found. */
inline fun <reified T : Enum<T>> enumValueOfOrNull(name: String): T? {
  return enumValues<T>().find { it.name == name.uppercase(Locale.ENGLISH) }
}

ZacSweers avatar Aug 09 '23 07:08 ZacSweers

It appears that a reified enumEntries() function wasn't added to the stlib but was called out as planned in the KEEP here

It will appear in Kotlin 1.9.20. The tracking issue for this function in stdlib is: https://youtrack.jetbrains.com/issue/KT-53154

nikitabobko avatar Aug 09 '23 08:08 nikitabobko