can you help me explaining how this function work? it uses Inline, reified, valueOf() and enumValues

341 Views Asked by At

I could really use your help in explaining this function. I have an Enum of countries with 2 string values, a country name, and a currency. The exercise is to use 2 string inputs, check if the enum has the countries, and then compare their currencies, return true or false accordingly. I manage to do it with 2 for loops and 2 ifs but I know this is not ideal. I then tried to use contains() and valueOf(input) but when the input is not in the enum it throws an illegal argument exception for valueOf()

if (values().contains(valueOf(country1.toUpperCase())) && values().contains(valueOf(country2.toUpperCase()))) {
    return valueOf(country1.toUpperCase()).currency == valueOf(country2.toUpperCase()).currency
    } else return false

I searched in here and found a valueOfOrNull() method that I don't quite get

inline fun <reified T : Enum<T>> enumValueOfOrNull(country: String): T? {
            return enumValues<T>().find { it.name == country.toUpperCase() }
        }

Can you help me explain how this works? I have no idea how the inline, reified T: Enum works and what does it return. Also, I just started learning lambdas so I have a basic idea of the .find {} part but I could use an explanation fo the it

I appreciate all your help and thank you very much.

1

There are 1 best solutions below

2
On BEST ANSWER

In Kotlin, inline functions get their bodies transformed in compile-time and, well, inlined at each of the call sites. While this requires more work from the compiler and leads to bigger binaries, inline functions are somewhat more flexible because, rather than compiling their bodies into one piece of bytecode for all, the compiler gets more additional information from each call site and may embed that into the inlined body, producing different results based on the calls. One example of such additional data that is embedded into the transformed inline function body is a lambda passed to the function from the call site, allowing for non-local control flow.

Another way that the compiler may transform the body for a particular call site is by embedding the actual generic type arguments from the call site. When producing a single compiled function body for all call sites, the compiler can't generate any code that takes the actual type argument into account, such as foo is T checks. In other words, the actual type arguments are erased. However, with inlined body for each individual call site, this becomes possible. The feature is called reified type parameters.

Then, enumValues is an intrinsic function that the compiler treats specially, which may be called on a reified type parameter that is a subtype of Enum (every enum class is), and then in the inlined function body there will be a call that returns the enum values. This is not the only intrinsic function that works with the reified type parameter during inlining: typeOf does this, too, and produces a KType token that one can use to introspect an actual type argument.