inline, noinline, crossinline — What do they mean?
I found Kotlin interesting and I’ve started to carefully migrate my Android codebase to Kotlin. You see, I’ve been a Java programmer since I can remember and I’ve not for anytime in my life used the keyword volatile.
I don’t know what it does, I’ve seen it in some weird APIs but I’ve not been bothered with it. I have refused to bring that behavior to Kotlin.
You see, I’ve been running into the inline
keyword a lot lately. And on rare occasions, I’ve stumbled on noinline
and crossinline
too. I don’t want them to be the new volatile
. I went through the inline functions docs, it gave a high level explanation on the keywords. I am not usually satisfied with API docs from the API providers and so I found this stackoverflow question. This made me to research more and I here’s what I’ve found:
Inline
This explanation was inspired by this answer.
Say you have a higher order function in Kotlin,
Here’s a cleaned up version of how the kotlin code will look like when it’s converted to Java:
This means that anytime you use the higher order function in your kotlin code, the Java translated code will end up looking something like this:
Imagine calling this lambda in a loop. You’ll end up creating N Function
objects.
adding the inline
keyword in your higher order function will prevent such. You’ll end up having your lambda’s code and the higher order function’s code inlined at the calling site.
Now after adding the inline
keyword, when your code is translated to Java, it will look something like this:
Now, you’ll be tempted to add the inline
keyword to all your higher order functions. With inline functions, you will not be able to access private members/methods of your enclosing class. You will need to make those members/methods internal
and then annotate them with @PublishedApi
.
Also, when using inline functions, you will be able to return from the lambda which in turn will return from the calling function. This is usually called non-local control flow.
Noinline
This one is easy.
Say you have multiple lambdas in your inlined function and you don’t want all of them to be inlined, you can mark the lambdas you don’t want to be inlined with the noinline
keyword:
Note that noinline
lambdas do not support non-local control flow, i.e you won’t be able to propagate your return to the calling function.
Crossinline
The crossinline
marker is used to mark lambdas that mustn’t allow non-local returns, especially when such lambda is passed to another execution context such as a higher order function that is not inlined, a local object or a nested function. In other words, you won’t be able to do a return
in such lambdas.
That’s all folks. Now let us move on to the next keyword.