The Programmers Guide To Kotlin - Inline Functions
Written by Mike James   
Tuesday, 25 June 2019
Article Index
The Programmers Guide To Kotlin - Inline Functions
Non-local returns
Reified Type

Kotlin provides many new ways to work with functions but in the end it all comes down to how these map onto Java's way of doing things. In this extract from the book on Kotlin by Mike James we look at how to work with and understand inline functions.

 

Programmer's Guide To Kotlin

Now Available as a Print Book

cover

You can buy it from: Amazon

Contents

Some Chapters Already Available On The Web

  1. What makes Kotlin Special (Book Only)
  2. The Basics: Variables, Primitive Types and Functions
  3. Control
  4. Strings and Arrays
  5. The Class & The Object
  6. Inheritance
  7. The Type Hierarchy 
            Extract  Type and its problems
            Extract  Smart Casts
  8. Generics
            Extract Basic Generics
            Extract Covariance & Contravariance
  9. Collections, Iterators, Sequences & Ranges
            Extract Iterators & Sequences
  10. Advanced functions 
  11. Anonymous, Lamdas & Inline Functions
            Extract    Annoymous and Lambda Functions
            ExtractInline Functions  **NEW!**
  12. Data classes, enums and destructuring
            Extract  Data Classes
            Extract 
         Delegated Properties 
  13. Exceptions, Annotations & Reflection
            Extract Annotation & Reflection 
  14. Working with Java
            Extract Using Swing  

Many of Kotlin's language innovations are about how you can use functions. As well as being able to use standalone "classical" functions, Kotlin also provides function expression and references, which allow you to pass functions to other functions. One of the problems is that this has resulted in a confusing menagerie of new and different function types.

When it comes to functions in Kotlin, there is usually more than one way to get a particular job done. 

Sections not included in this extract:

  • Anonymous Functions & References
  • Lambda Functions
  • Lambdas & Anonymous Functions As Extensions
  • DSLs & Metaprogramming
  • No Local Return
  • Compact Lambdas, it, _ & IIFE
  • Closure

 

Inline Functions

Functions are good for efficiency in the sense that they allow you to reuse a block of code as many times as you like, but without having to include the code multiple times in your program. However, functions are also bad for efficiency in that each Kotlin function creates an object to host each one, and the need to create a closure also slows things down. There are overheads in using a function as well as advantages.

An alternative way of implementing functions is for the compiler to essentially copy the code of the function into any location it is called.

For example if you call the sum function:

var ans=sum(1,2)

then the compiler would convert this into the equivalent:

var ans=1+2

There is no trace of the function in the generated code. The compiler simply copies the code in the function to the call location and removes the function call and return – after all there is no function to return from any more.

Of course, a real function would most likely have tens of lines of instructions and these would be copied and hence duplicated in the compiled code each time the function was called. It might make your application larger but it is often worth the trade off.

In Kotlin you can ask the compiler to inline a function using the inline modifier. Notice that you can only inline named functions and not anonymous or lambda functions – however, functions passed to inline are inlined. This is an important point and you could say that the whole point of inlining is to remove the expense of passing functions into other functions.

For example:

inline fun sum(a:Int,b:int){
 return a+b
}

Now when you call sum the function isn't called in the usual way and the return is removed as there is nothing to return from. If you try this function out the compiler will generate a warning that it is far to simple a function to bother inlining. You can take its advice or ignore it.

This would be the end of the story but inlining code creates a number of differences between a standard function and an inlined function.

The most basic is that an inline function cannot call itself and it cannot call a function that in turn calls it. If you understand how inline functions are implemented you will see why this is so. At run time there is no function to call.

Inlining a function will cause the compiler to inline any functions that are passed to it via its parameters. If you don't want a passed function to be inlined then you can use the noinline modifier.

For example:

inline fun myfuncDisplay(noinline a:arith){
        println(a(1,2))
    }

will inline the call to myfunc but not the passed arith function.

You can also inline properties that don't have backing fields – both the get and put or just one of them. All you have to do is put inline in front of the property or the getter or setter of your choice. The get or set function is inlined in the usual way. The reason you can't use a backing property is that the inline code is generated outside of the class/object and so the inline getter and setter cannot access any internal variables.



Last Updated ( Tuesday, 25 June 2019 )