Idiomatic Kotlin: Noinline and Crossinline
This article is a part of the Idiomatic Kotlin series. The complete list is at the bottom of the article.
If you have been following this series, you should be very familiar with inline functions and the consequences of using them. Today, we will talk about minimizing those consequences by adding restrictions.
Noinline
The noinline
modifier allows you to mark a lambda parameter of an inline function to prevent inlining of that same lambda. Now, why would you need to do that? Let’s look at some cases.
Remember reified type parameters? Using reified type parameters requires you to add the inline modifier. This will force all the lambda parameters of that inline function to be inlined. You can mark those lambda parameters that you don’t want to inline with the noinline
modifier. As a recap, this code
will output a decompiled code like this
The lambda function was automatically inlined as expected. Adding noinline modifier to the func
argument will result in a decompiled code like this.
No surprises. The compiler just ignores the inline modifier and proceed to compile the lambda as an anonymous function.
You can also use noinline
to explicitly specify lambda parameters that should not be inlined in cases where you have multiple lambda parameters.
Crossinline
Crossinline allows you to mark a lambda to forbid it from using non-local returns. If you remember, inline lambdas interprets return
as non-local returns and return
is not allowed on non-inlined lambdas. Let’s see a simple example and also to refresh our memory.
Running this will not output Main finished
. This is because the return
inside the lambda is a non-local return and will return from the main
function. Marking the lambda parameter as crossinline
will not allow you to perform non-local return on the lambda.
When is crossinline applicable? Let’s look at a simple case.
Let’s say we have a higher order function that accepts a message and an instance of function type. We know that the function type arguments in a non-inlined function are not allowed to return. Therefore, calling this function from an inline function will throw a compile time error. This is because an inlined lambda is allowed to perform non-local returns. To resolve this, you can mark the lambda parameter of the inline function as crossinline to prevent the call-site from using return.
Check out the other articles in the idiomatic kotlin series. The sample source code for each article can be found here in Github.
- Extension Functions
- Sealed Classes
- Infix Functions
- Class Delegation
- Local functions
- Object and Singleton
- Sequences
- Lambdas and SAM constructors
- Lambdas with Receiver and DSL
- Elvis operator
- Property Delegates and Lazy
- Higher-order functions and Function Types
- Inline functions
- Lambdas and Control Flows
- Reified Parameters
- Noinline and Crossinline
- Variance
- Annotations and Reflection
- Annotation Processor and Code Generation