Functional interfaces: Self-loathing in Kotlin
Tags: kotlin, functional, java
Published: 2019-07-12 12:19:47

> This post is a copy from previous posts on Medium ([initial](https://medium.com/@ranilch/self-loathing-in-kotlin-d17431bcf21e), [follow-up](https://medium.com/@ranilch/functional-interfaces-self-loathing-in-kotlin-follow-up-26a23868858c)) But since I'm planning on deleting my Medium account I moved them here.

Kotlin is a wonderful programming language. After roughly 12 years of Java programming working with Kotlin felt like putting on glasses after years of squinting: there's so much to love.

But like with every relationship, some of the quirks you only discover later in your life together. After migrating more and more Java code to Kotlin code, I noticed something rather odd and frankly a bit annoying.

It's the way __Kotlin__ handles __functional interfaces__.

# Java 7: a blast from the past

Let's go back in time to a world without lambdas. It was terribly verbose!

```java
interface JavaInterface {
    String doSomething(Item item);
}

String delegateWork(JavaInterface f) {
    return f.doSomething(item);
}

void doWork() {
    delegateWork(new JavaInterface() {
        @Override
        public String doSomething(Item item) {
            return "Item = " + item;
        }
    });
}
```

![](https://thepracticaldev.s3.amazonaws.com/i/3af1x7zj1x62za61vwq5.jpg)

# Java 8: Lambdas to the rescue!

Finally Java 8 gave us Lambdas and we could get rid of a lot of code and focus on what's important. Also we weren't forced to write our own functional interface for every simple function we could just use some that oracle provided such as: `java.util.function.Function<T, R>`

```java
@FunctionalInterface
interface JavaInterface {
    String doSomething(Item item);
}

String delegateWork(JavaInterface f) {
    return f.doSomething(item);
}

String delegateOtherWork(Function<Item, String> f) {
    return f.apply(item);
}

void doWork() {
    delegateWork(item -> "Item = " + item);
    delegateOtherWork(item -> "Item = " + item);
}
```

Things were nice until you realised that even though you now had function types they still weren't first-class citizen in the language. Want proof? Guess how many "Types of Functions" had to be introduced in Java? One? Three? Five?

# 43!

Don't believe me, see for yourself: https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html

And if that's not enough for you, add jOOL to the mix and you have access to 35 more: https://github.com/jOOQ/jOOL/tree/master/jOOL/src/main/java/org/jooq/lambda/function
Because who wouldn't love coming across a method signature that looks like this:

```java
Function5<String, String, String, String, String, Tuple3<String, String, String>> higherOrder(Function12<String, Integer, String, Object, Object, Object, BiFunction<String, Integer, String>, String, Integer, Long, String, Double, Optional<Tuple2<String, String>>>)
```

😜 side note: jOOL is actually quite a neat library, and worth checking out.

# Kotlin help us!

Now let's add Kotlin to the mix. In Kotlin functions are first-class citizen. So no need to remember dozens of slightly different function types. You just need to remember Kotlin's Function Type Syntax:

```kotlin
(Parameter1Type, Parameter2Type, ParameterNType) -> ReturnType
```

That's it, that's all there's to it.

# Trouble in paradise

So ok, why are we here, what's the problem?

As mentioned earlier, as I migrated more and more code from Java to Kotlin. I came across some issues when working with custom functional interfaces. Because sometimes you want that additional descriptiveness.

Let's go back to our Java 8 example

```java
@FunctionalInterface
interface JavaInterface {

    String doSomething(Item item);
}

class JavaComponent {

    private Item item = new Item();

    String delegateWork(JavaInterface f) {
        return f.doSomething(item);
    }

    String delegateOtherWork(Function<Item, String> f) {
        return f.apply(item);
    }
}
```

Now let's use it from Kotlin code

```kotlin
delegateWork { "Print $it" }
delegateOtherWork { "Print $it" }
```

Nice this is great, just what we expected! Ok now let's migrate this `JavaComponent` class to Kotlin. Notice we've changed the `java.util.function.Function<Item, String>` to a Kotlin function type `(Item) -> String`

```kotlin
class KotlinComponent(private val item: Item = Item()) {

    fun delegateWork(f: JavaInterface): String {
        return f.doSomething(item)
    }

    fun delegateOtherWork(f: (Item) -> String): String {
        return f.invoke(item)
    }
}
```

Let's see what happens when we use these higher order functions from Java code.

```java
delegateWork(item -> "Print: " + item);
delegateOtherWork(item -> "Print: " + item);
```

Nothing out of the ordinary as expected we can use the same lambda for both methods. Let's see what happens when we do what we'd expect in Kotlin:

```kotlin
delegateWork { "Print $it" }

Error: Kotlin: Type mismatch: inferred type is () -> String but JavaInterface was expected
```

What happened? It seems the compiler can't figure out that the signature of the lambda is the same as the functional interface method. https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions

So we have to explicitly say what we expect:

```kotlin
delegateWork(JavaInterface { "Print $it" })
```

I think this is rather disappointing but it's not too bad. Now let's see what happens when we also migrate the interface to Kotlin:

```kotlin
interface KotlinInterface {
    fun doSomething(item: Item): String
}

class KotlinComponent(private val item: Item = Item()) {

    fun delegateWork(f: KotlinInterface): String {
        return f.doSomething(item)
    }

    fun delegateOtherWork(f: (Item) -> String): String {
        return f.invoke(item)
    }
}
```

When we use the `KotlinComponent` class from Java, as expected nothing changes, the lambdas remain exactly the same. What if we use it from Kotlin code:

```kotlin
delegateWork { "Print $it" }

Error: Kotlin: Type mismatch: inferred type is () -> String but KotlinInterface was expected
```

It seems the SAM conversion fails again. Now what if we just explicitly mention the Interface like we did before?

```kotlin
delegateWork(KotlinInterface { "Print $it" })

Error: Kotlin: Interface KotlinInterface does not have constructors
```

This didn't help either. We need to create an anonymous object to make it work:

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

Yikes! This feels like working with Java 7 all over again. Sadly this is because Kotlin doesn't yet support SAM conversion for Kotlin interfaces so we have to create this anonymous object. See also: 
https://youtrack.jetbrains.com/issue/KT-7770
https://stackoverflow.com/a/43737962/611032

# Alias time!

So how can we avoid these verbose anonymous objects and still use a custom name for the function? We use a type alias:

```kotlin
/**
 * Very helpful comment.
 */
typealias KotlinFunctionAlias = (Item) -> String

fun delegateAliasWork(f: KotlinFunctionAlias): String {
  return f.invoke(item)
}
```

So now we can pass in a lambda the way we'd expect and we still have the benefit of a custom name for the function.

```kotlin
delegateAliasWork { "Print $it" }
```

So all is is well then, case closed, time to go home. Unfortunately not quite.

## Lost in translation

One minor issue with type aliases is that while you can name the function type, you cannot name the method name:

```kotlin
val iface: JavaInterface = JavaInterface { "Print $it" }
iface.doSomething(item)

val alias: KotlinFunctionalAlias = { item -> "Print $item" }
alias.invoke(item)
alias(item)

```

Choosing good names for the type alias and variable can mitigate the issue. Luckily we developers are great at naming things 😜

## Type safety

The bigger issue is that while the type alias gives us a different name, they aren't really different types, so we're not actually type safe.

Let's look at a Java example with two functional interfaces that have the same method signature.

```java
JavaInterface1 f1 = item -> "Print " + item;
JavaInterface2 f2 = item -> "Print " + item;
f1 = f2;

Error: java: incompatible types: JavaInterface2 cannot be converted to JavaInterface1
```

This is what we'd expect we don't want to mix apples and oranges here.

What happens if we do the same thing with our Kotlin type aliases? (I think you know where I'm going with this)

```kotlin
var f1: KotlinFunctionAlias1 = { item -> "Print $item" }
var f2: KotlinFunctionAlias2 = { item -> "Print $item" }
var f3: (Item) -> String = { item -> "Print $item" }
f1 = f2
f2 = f3
f1 = f3
```

This works fine, the compiler doesn't complain because like I mentioned they aren't actually different types. They're all simply: `(Item) -> String`

# Solutions

So let's quickly recap the different ways we can deal with Kotlin's missing SAM conversion for Kotlin interfaces and their upsides and downsides

## Leave functional interfaces as Java interfaces

\+ Good Java interoperability
\+ Support for custom method name
\+ Type safe

\- Need to prefix Kotlin lambda with interface name
\- Additional parentheses needed
\- Need to maintain Java code

## Use a type alias for Kotlin function types

\+ Good Java interoperability
\+ Easy to use

\- Not type safe
\- No custom method name

## Use inline classes

Another option we haven't yet discussed is the use of the experimental Kotlin inline classes. You could "wrap" a Kotlin Function with an inline class.

```kotlin
inline class KotlinInlineInterface(val doSomething: (Item) -> String)

fun delegateInlineWork(f: KotlinInlineInterface): String {
    return f.doSomething.invoke(item)
}

delegateInlineWork(KotlinInlineInterface { "Print $it" })
```

Even though this works, I don't thinks it's an appropriate way of using inline classes. Also Java interoperability isn't currently supported: https://kotlinlang.org/docs/reference/inline-classes.html#mangling

## Always use Kotlin function types

Yes you could just use `(ParamT) -> ReturnT` types everywhere. Often that will be sufficient but as your application grows it might get harder to read and maintain and more error-prone.

## Live with anonymous objects

Of course if you don't mind, you can just live with the anonymous objects, hope that someday Kotlin will support full SAM conversion and make use of the wonderful IDE integration to migrate your anonymous objects to lambdas

¯\\_(ツ)_/¯

# Jetbrains Feedback

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

{% twitter 1122951159482855424 %}

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](https://kotlinlang.org/docs/reference/using-maven.html) / [Ant](https://kotlinlang.org/docs/reference/using-ant.html)) 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:

```kotlin
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?

```kotlin
delegateWork(KotlinInterface { item -> "Print $item" }

Error: Interface KotlinInterface does not have constructors
```

Bummer! We still need an anonymous object.

What about using a __Java functional interface in Kotlin__ code?

```kotlin
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:+NewInference

This 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? It 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.