Kotlin can’t choose

While giving a presentation on Kotlin’s lambdas, someone asked me a tough question. I actually had no idea how to answer it so I took that question home and gave it some thought. Now that I have finally answered it, I thought it would be good to share this question and its answer with everyone.

The question

Let’s assume we have the following methods, how do you invoke one method over the other ?

The question explained

For those of you not familiar with Kotlin’s syntax, let’s take a step back and understand what the question actually is. We have declared two methods :

  • one that receives an object and a lambda with no argument.
  • another that receives an object and a lambda with receiver that will be called on the object received as first parameter (which we legitimately call “receiver”). 
    FYI : Those lambdas with receiver (sometimes also called lambda extension) are similar to extension functions.

If declared without the other one, we would call each method with code looking like this :

But, in our case, since there are 2 methods, Kotlin complains :

Alt+Enter will not help you with this choice. So, how can we call one method over the other ?

Calling the first method

The first thing I tried was to use object like so :

As it turned out, it worked and I was able to call the first method.

You may be wondering what is object in Kotlin. In short, they are a way to declare anonymous classes like we would in Java. I highly encourage you to read more about object in the documentation in you are not familiar with it.

Using this solution, I’m creating an anonymous class of type kotlin.jvm.functions.Function0 the same way Java would when calling this method from Java code.

Calling the second method

Confident from my first try, I thought may be I could call the second method with the following code :

But Kotlin doesn’t like that and complains again :

But, this time, Alt+Enter gives us a solution :

This solution actually makes sense.

OK but why ?

To better understand what happened, let’s take another step back and look at what happens when we create an extension function
What Kotlin actually does is create a static method which receives the object as first parameters. This behavior is quite obviously exposed when calling a method extension (first snippet) from java code (second snippet) :

Calling Kotlin method extension in Java

It is therefore understandable that if we were to call the second method in Java, we would need to create an anonymous class that receives the receiver as first parameter and this is exactly what we have done when calling the second method using object.

In case you were wondering, the anonymous class we have created is of type kotlin.jvm.functions.Function1

There must be a better way

As we all know, Kotlin aims at being cleaner and shorted than Java. Using object and overriding the invoke method is a lot of boilerplate and feels too much like Java. There must be a better way.

Kotlin is actually a lot of fun, I mean, literally a lot of fun and we can declare functions directly when calling methods :

“: Unit” is not needed as for regular functions

This solution is actually better because we will be able to use this inside the lambda with receiver (where this represents the String passed as first parameter) where we couldn’t using the object solution. There is also a lot less boilerplate code and it’s much closer to Kotlin idioms.

Finally, another solution is to create the function and store it in a variable like so :

Although this works just as well, I would not recommend using it unless you want to re-use your lambda elsewhere as it decouples the code from the place where it is called for no good reason.

Conclusion

The problem came from the fact that Kotlin is very powerful but still fairly new for a lot of people. We are still getting used to its syntax and all the goodies it has in store for us. 
Also, I like to take out of it, one more time, that every question is a chance to learn something new.