Extension function on a generic type

203 views Asked by At

I am new in Kotlin and I am trying to understand type alias and functions.
I have the following example:

interface EmptyInterface
typealias GenericCase<T> = T.(EmptyInterface) -> T

val myFunctionVariable: GenericCase<String> = {
    _ -> "Hello world!"
}

So far what I understand is that I extend what ever T is defined with a function that accepts as argument an EmptyInterface and returns a T. So the myFunctionVariable is a function that should be called passing an EmptyInterface

But the following code does not compile

class a: EmptyInterface
println("${myFunctionVariable(a())}")  

I need to pass a String as the first parameter:

class a: EmptyInterface
println("${myFunctionVariable("",a())}")

Why is the string needed as the first parameter? T.(EmptyInterface) -> T which in this case is String.(EmptyInterface) -> String has only 1 parameter. Could someone please explain this?

2

There are 2 answers

2
zsmb13 On

The T. in the type T.(EmptyInterface) -> T means that this function is an extension function on T. So the regular way to call this function is to acquire a T instance, and call it on that instance, as if it was a member function. In the case of your example, where you chose T to be a String, you have to call the function on a String instance:

"foo".myFunctionVariable(a())

The syntax you've used is an alternative way to call this extension, passing in the receiver as if it was the first parameter of the function (which, at the bytecode level, it actually is):

myFunctionVariable("foo", a())

If you wish to use your function with this syntax, however, it's better to declare it to take two parameters, as this invocation of an extension function can be quite unexpected.

(There's some more info about how you can go back and forth between a function that's an extension on a type and one that takes it as a first parameter in this answer.

6
gidds On

In the type T.(EmptyInterface) -> T, the first T is the receiver: an instance that the function is called upon, and which becomes this within the function definition.  (Similar to an extension function.)

Effectively, the receiver becomes a hidden first parameter to the function; as you discovered, if you try to call the function directly, you'll need to give it explicitly.

The language spec for it is here; some other answers may also help.