Functional interfaces: Self-loathing in Kotlin (follow-up)

Ranil Wijeyratne
2 min readMay 6, 2019

--

In my last post I wrote about Kotlin’s handling of functional interfaces: https://medium.com/@ranilch/self-loathing-in-kotlin-d17431bcf21e

There has been a short discussion on Reddit: https://www.reddit.com/r/Kotlin/comments/bipj0q/functional_interfaces_selfloathing_in_kotlin/

Since then I got a response from Roman Elizarov on the subject

I tried the mentioned Kotlin compiler option:

// Gradle Kotlin DSL
tasks.withType<KotlinCompile> {
kotlinOptions.freeCompilerArgs += "-XXLanguage:+NewInference"
}
// Gradle Groovy DSL
compileKotlin {
kotlinOptions {
freeCompilerArgs += "-XXLanguage:+NewInference"
}
}

If you’re more into other build systems, refer to Kotlin documentation (Maven / Ant) to see how to pass Kotlin compiler arguments.

Problem solved?

First let’s see what happens when we use a Kotlin functional interface in Kotlin code:

fun delegateWork(f: KotlinInterface): String {
return f.doSomething(item)
}
delegateWork { item -> "Print: $item" }Error: Type mismatch: inferred type is (Nothing) -> TypeVariable(_L) but KotlinInterface was expected

What about explicitly specifying the interface?

delegateWork(KotlinInterface { item -> "Print $item" }Error: Interface KotlinInterface does not have constructors

Bummer! We still need an anonymous object:

delegateWork(object : KotlinInterface {
override fun doSomething(item: Item): String {
return "Print $item"
}
})

What about using a Java functional interface in Kotlin code?

fun javaInterface(f: JavaInterface) {
val res = f.doSomething(item)
output(res)
}
javaInterface { item -> "Print: $item" }

Finally: just what we expected. All is well, beer well deserved!

Patience young Jedi

If you’re observant, you’ll see this during the build:

w: ATTENTION!
This build uses unsafe internal compiler arguments:
-XXLanguage:+NewInferenceThis mode is not recommended for production use,
as no stability/compatibility guarantees are given on
compiler or generated code. Use it at your own risk!

So what does that mean? In means what it says here: this isn’t really safe to use yet. But knowing JetBrains is working in that direction I’d suggest that we, for now, do things the following way (most favourable to least favourable)

  1. Keep functional interfaces as Java code
  2. Use type aliases for Kotlin function types (if you can live with potentially mixing apples and oranges)
  3. Live with the anonymous objects

Thanks for reading. As always I’m open to criticism and feedback.

--

--