Kotlin Inline functions

In Kotlin, the higher order functions or lambda expressions, all stored as an object so memory allocation, for both function objects and classes, and virtual calls might introduce runtime overhead. Sometimes we can eliminate the memory overhead by inlining the lambda expression.

In order to reduce the memory overhead of such higher order functions or lambda expression we can use the inline keyword which ultimately requests the compiler to not allocate memory and simply copy the inlined code of that function at the calling place.

Kotlin program –

filter_none

edit
close

play_arrow

link
brightness_4
code

fun higherfunc( str : String, mycall :(String)-> Unit) {
    //inovkes the print() by passing the string str
    mycall(str)
}
    // main function
fun main(args: Array<String>) {
    print("GeeskforGeeks: ")
    higherfunc("A Computer Science portal for Geeks",::print)
}

chevron_right


Bytecode –
Like Java, Kotlin is also platform independent language so it converts into the bytecode first. We can get the bytecode as Tools -> Kotlin -> Show Kotlin Bytecode . Then, decompile to get this bytecode.



In the above bytecode, the main part to focus is

mycall.invoke(str)

mycall invokes the printMe function by passing the string as parameter. While invoking the printMe(), it would create an additional call and increases memory overhead.

It works like that-

mycall(new Function() {
        @Override
        public void invoke() {
         //println statement is called here.
        }
    });

If we call a large number of functions as parameters each of them would add up to the method count then there is a vast impact on the memory and performance.

What inline keyword will do in the above program ?

filter_none

edit
close

play_arrow

link
brightness_4
code

inline fun higherfunc( str : String, mycall :(String)-> Unit){
    //inovkes the print() by passing the string str
    mycall(str)
}
    // main function
 fun main(args: Array<String>) {
    print("GeeskforGeeks: ")
    higherfunc("A Computer Science portal for Geeks",::print)
}

chevron_right


Bytecode-

With the help of inline keyowrd the println lambda expression is copied in the main function in the form of System.out.println and no further calls required.

Non-local control flow-

In Kotlin, if we want to return from a lambda expression then Kotlin compiler does not allow to do so. With the help of inline keyword, we can return from the lambda expression itself and exit the function in which inlined function is called.

Koltin program of using return in lambda expression-

filter_none

edit
close

play_arrow

link
brightness_4
code

var lambda = { println("Lambda expression")  
              return }      // normally lambda expression does not allow return 
                           // statement, so gives compile time error
fun main(args: Array<String>) {
    lambda()
}

chevron_right


Output:


Error:(4, 5) Kotlin: 'return' is not allowed here

Normally it does not allow to return from lambda and it gives error.

filter_none

edit
close

play_arrow

link
brightness_4
code

var lambda1 = { println("Lambda expression")}
  
fun main(args: Array<String>) {
    lambda1()
}

chevron_right


Output:

Lambda expression

Normally without it works fine and print the statement.

Kotlin program of using return in lambda while passing as an argument to inlined function-

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>){
    println("Main function starts")
    inlinedFunc({ println("Lambda expression 1")
    return },      // inlined function allow return statement in lambda expression
                   // so, does not give compile time error
  
    { println("Lambda expression 2")} )
  
    println("Main function ends")
}
    // inlined function
inline fun inlinedFunc( lmbd1: () -> Unit, lmbd2: () -> Unit  ) {  
    lmbd1()
    lmbd2()
}

chevron_right


Output:

Main function starts
Lambda expression 1

Explanation:
Here, we passed two lambda expression as arguments to the inlinedFunc() function. While calling the inlined function from the main, we pass both as its arguments. In the inlined function, lmbd1() invoked the first expression and return keyword force the lambda expression itself and the main function from where it is called to exit.

crossline keyword-

In the above program, return in lambda exits the inline function as well as its enclosing function. So to stop returning from the lambda expression we can mark it using the crossline. It will throw a compiler error if sees any return statement in lambda expression.

Kotlin program of using crossline keyword-

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>){
    println("Main function starts")
     inlinedfunc({ println("Lambda expression 1")
        return },     // It gives compiler error
         { println("Lambda expression 2")} )
  
    println("Main function ends")
}
  
inline fun inlinedfunc( crossinline lmbd1: () -> Unit, lmbd2: () -> Unit  ) {
    lmbd1()
    lmbd2()
}

chevron_right


Output:

Error:(6, 9) Kotlin: 'return' is not allowed here

noinline-

In Kotlin, if we want only some of the lambdas passed to an inline function to be inlined, we can mark some of function parameters with the noinline modifier.


filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>){
    println("Main function starts")
    inlinedFunc({ println("Lambda expression 1")
        return },     // It does not compiler time error
        { println("Lambda expression 2")
            return } )    // It gives compiler error
  
    println("Main function ends")
}
  
inline fun inlinedFunc( lmbd1: () -> Unit, noinline lmbd2: () -> Unit  ) {
    lmbd1()
    lmbd2()
}

chevron_right


Output:

Error:(11, 13) Kotlin: 'return' is not allowed here

Reified Type Parameters-

Sometimes we need to access the type of parameter passed during the call. We have to simply the pass of parameter at the time function calling and we can retrieve the type of the parameter using reified modifier.

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>) {
    genericFunc<String>()
}
  
inline fun <reified T> genericFunc() {
    print(T::class)
}

chevron_right


Output:

class kotlin.String

Inline properties-

Inlined function copy the code to the calling place, similarly inline keyword copy the inline properties accessor methods to calling place. The inline modifier can be used on accessors of properties that don’t have a backing field.

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(args: Array<String>) {
    print(flag)
}
fun foo(i: Int ): Int{
    var a =  i
    return a
}
inline var flag : Boolean
    get() = foo(10 ) == 10
    set(flag) {flag} 

chevron_right


Output:

true


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : nidhi_biet



Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.