The Programmers Guide To Kotlin - Anonymous and Lambda Functions
Written by Mike James   
Monday, 29 October 2018
Article Index
The Programmers Guide To Kotlin - Anonymous and Lambda Functions
Lambda Functions
Closure

Closure

Closure is one of the most mystifying aspects of lambdas. The Kotlin documentation makes a lot of the fact that a lambda has access to the local variables of any function that encloses it, but this is really just the way that local variable work rather than closure.

Closure, in the way that most languages implement it, means having access to variables that were local but are no longer in scope. The simplest example of this is when a function returns a lambda. While the function is executing, the lambda has access to variables that are local to the function – but not only this, it has access to them when the function has completed and the local variables have been, in principle, destroyed. You can think of this as the lambda "capturing" the variables in a closure.

Kotlin supports this sort of closure. For example, if we define a function that returns a simple lambda:

fun myFunction():()->Unit{
    var a=1
    var lambda= {println(a);a=a+1}
    return lambda
}

There are several interesting things about this function. The first is that its return type is ()->Unit, i.e. it returns a function that accepts no parameters and returns nothing, i.e. Unit. This is indeed the type of the lambda it returns. The lambda in question simply prints the value of a and adds one to it. Note that a is a local variable in myFunction and it is only accessible from within myFunction and it is destroyed when myFunction returns, i.e. it normally only exists while myFunction is active.

If you now call myFunction to get an instance of the lambda:

var mylambda=myFunction()

and then call the lambda twice:

    mylambda()
    mylambda()

what do you think will happen?

The answer is that it prints 1 followed by 2. The instance has access to the local variable that should have been destroyed when myFunction terminated, and it not only has access to its initial value but it can modify it. 

It is important to realize that each time you return a new instance of the lambda the local variable a is a new local variable.

For example:

var mylambda1=myFunction()
var mylambda2=myFunction()
mylambda1()
mylambda1()
mylambda2()
mylambda2()

You will see 1,2 and then 1,2 printed because the variable a captured by mylambda1 is not the same as the a captured by mylambda2.

Closure works with named and anonymous functions as well as pure lambda functions. In the case of named functions it has to be a local function and you have to use the :: operator.

For example:

fun myFunction():()->Unit{
    var a=1
    fun namedFunction(){
        println(a)
        a=a+1
    }     var lambda= ::namedFunction
    return lambda
}

If you are unfamiliar with lambda functions or functions as first class objects you might be wondering what use closure is?

There are a number of standard uses of closure, but perhaps the most useful is when you are defining an event handler of a callback function. Lambdas and anonymous functions make supplying a callback very easy. However, the callback is usually designed to process the end result of some long running task and this usually involves the function that created the callback. If the task wasn't long running you would have simply waited for it to complete and then processed its return value. The callback breaks up the original function into before the task and after the task. By allowing the callback access to the function’s local variables, closure allows a degree of communication between the original function and the callback.

Inline Functions

final version in book

Non-Local Returns

final version in book

Reified Type

final version in book

Summary

 

  • You can store a reference to an anonymous function in a variable or pass the function as an argument to another function.

  • You can store a reference to a named function in a variable or parameter using the reflection reference operator ::

  • A reference to a lambda function can also be stored in a variable or passed as a parameter.

  • A lambda is defined as { parameter list -> code }

  • A lambda, anonymous or named function can be used as extension functions.

  • The shortened forms that you can use to define and call functions make them very suitable to implement DSLs and metaprogramming.

  • You cannot have a return in a lambda but you can use a qualified return.

  • Lambdas can be simplified to the point where they are difficult to understand. You can use it as a default parameter of a single parameter lambda, leave out parameters using underscore, and execute a lambda immediately.

  • All Kotlin functions support closure where variables that were in scope at the time the function was created remain accessible to the function even after they have gone out of scope.

  • Inline functions can be used to improve performance and add features such as non-local returns and reification

 

This article is an extract from: 

Programmer's Guide To Kotlin Second Edition

kotlin2e360

You can buy it from: Amazon

Contents

  1. What makes Kotlin Special
  2. The Basics:Variables,Primitive Types and Functions 
  3. Control
         Extract: If and When 
  4. Strings and Arrays
  5. The Class & The Object
  6. Inheritance
  7. The Type Hierarchy
  8. Generics
  9. Collections, Iterators, Sequences & Ranges
        Extract: Iterators & Sequences 
  10. Advanced functions 
  11. Anonymous, Lamdas & Inline Functions
  12. Data classes, enums and destructuring
        Extract: Destructuring 
  13. Exceptions, Annotations & Reflection
  14. Coroutines
        Extract: Coroutines 
  15. Working with Java
        Extract: Using Swing ***NEW!

<ASIN:B096MZY7JM>

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

 

Banner


Google Adds Multiple Database Support To Firestore
04/03/2024

Google has announced the general availability of Firestore Multiple Databases, which can be used to manage multiple Firestore databases within a single Google Cloud project.



Generative AI Training For All On Coursera
04/03/2024

Generative AI is on the loose, getting into business and commerce as well as into art, poetry and coding. Already useful, it  will become ever more useful as long as we use it properly. Coursera  [ ... ]


More News

raspberry pi books

 

Comments




or email your comment to: comments@i-programmer.info

<ASIN:1871962536>

 

 

 



Last Updated ( Saturday, 03 November 2018 )