In Kotlin, an inline function is a function whose body is copied to every place where the function is called; essentially, the function code is inlined into the calling code at compile-time. This can result in faster execution because it eliminates the overhead of creating a new stack frame for each function call. In addition, inline functions can also have lambda parameters, and the function body can use non-local returns when the lambda is invoked. For example, consider the following inline function that accepts a lambda:
inline fun forEach(names: List<String>, action: (String) -> Unit) {
for (name in names) {
action(name)
}
}
When using an inline function like this, the lambda expression passed to the ‘action‘ parameter will be inlined, and there will be no overhead in creating a new stack frame for each iteration of the loop. This can result in faster execution, especially if the list contains a large number of elements.
On the other hand, a crossinline function is a function whose lambda parameters cannot be used as non-local returns. In other words, the lambda expression cannot be used to return control to the calling function. This is because when a lambda is passed to a function as a parameter, the function can be suspended, and control can be passed to another part of the program. If the lambda expression is allowed to use non-local returns, it could cause unexpected behavior or even a runtime error. To prevent this, we can use the ‘crossinline‘ keyword to indicate that the lambda parameter should not have non-local returns. For example, here is a crossinline function that accepts a lambda:
inline fun runAndPrint(crossinline block: () -> Unit) {
block()
println("Function executed successfully")
}
In this function, the ‘block‘ parameter is marked with the ‘crossinline‘ keyword, which means that the lambda expression cannot use non-local returns to terminate the function early.
So, when should we use an inline function versus a crossinline function? Use an inline function when you want to eliminate the overhead of creating a new stack frame for each function call, especially when the function will be called many times. Use a crossinline function when you want to ensure that the lambda expression passed to the function cannot use non-local returns to terminate the function early, to prevent unexpected behavior.