I’m curious how it is possible to call lambda function with receiver just like belows in two different ways. And what is considered the best practice between two?
Here is a simplified implementation of kotlin ‘with’ construct.
Thank you.
method #1
public inline fun <T, R> with(receiver: T, block: T.() → R): R {
return receiver.block()
}
method #2
public inline fun <T, R> with(receiver: T, block: T.() → R): R {
return block(receiver) // how this is possible?
}
This is because the Kotlin compiler exposes the fact that lambdas with receivers are, under the hood, just a static function with the receiver being the first parameter. This is exposed for convenience-sake and has no crazy implications or downsides.
By the way, how can I get the static function generated by the compiler?
I tried Intellij providing decompile tools, but it does not seems to generate what I want to see.
Well, this is an inline function, and so instead of generating a real lambda, the compiler just inlines the body of this function with the body of the “lambda” into the call site right away. This is an optimization to make life much easier, but if you want, you can make the function not inline, and then you’ll see the generated lambda
Yes, I know that this is inline function so it is copied to the code.
But the part you mentioned ‘under the hood’ is what i want to see. Actual code translated to like below maybe…?
// this is imaginary code I think compiler generated. But where I can see it?
val function = (block as Function1)
function.invoke(receiver)
Well, that doesn’t get generated at all because the actual block itself also gets inlined. If you want to see this at the call site directly, make the block parameter noinline