Error using `also` method

Why would this code not work?

val f: (String) -> Unit = { it -> println(it.length) }
val x = "hello".also(::f)

This prints out these error messages:

error: type inference failed: inline fun <T> T.also(block: (T) -> Unit): T
cannot be applied to
receiver: String  arguments: (KProperty0<(String) -> Unit>)
val x = "hello".also(::f)
                ^
error: type mismatch: inferred type is KProperty0<(String) -> Unit> but (String) -> Unit was expected
val x = "hello".also(::f)
                     ^

While

val x = "hello".also(::println)

would work, why would above not? What is KProperty0<> from the error message?

It needs to be

val x = "hello".also(f)

The reference syntax ::f would work only if f is a function. But it is a property that holds a function.

Alternatively, you can change f to be a function.

1 Like

Oh I see… Thanks for the explanation!

But now I wonder.
In case of lambda expressions, for example,

val square: (Int)->Int = { x -> x * x }

We use square just as if it was a function

square(2)

If square is not a function, but a property that holds a function,
what’s happening under the hood so that we could use the notation square(2)?

Under the hood it calls square.invoke(2). There just happens to be a shorthand syntax for it (see invoke operator overloading).

It is a bit inconsistent that there is not a shorthand syntax for function references, too.

1 Like

Thanks, that helped me clarify quite a lot :slight_smile: