Lambda

Lambda is a block of code represents function block in kotlin but lambda has most of the properties of a function, but it is more powerful than function in kotlin

Lambdas are used to minimize the code and also to pass the block of code as parameter to another functions, when you are using functions, you cannot pass one function as parameter to another functions but in case of lambdas you can do.

You can pass the lambda as parameter to a normal function in kotlin

lambdas are also called as function literals, There are two types of function literals in Kotlin:

  • Lambda expression
  • Anonymous function
Lambda expression is always surrounded by curly braces,

{println("hello Martian")}

You can store the lambda expression in a variable.


var lambdaAsVariable = {println("hello Martian")}

You can invoke a lambda expression just like functions in kotlin. You can store the lambda expression in a variable.


var lambdaAsVariable = {println("hello Martian")}
lambdaAsVariable()

You can also invoke a lambda using the run() method and below is lambda without return value.


fun main(args:Array<String>)
{
    var lambdaMoreParams = {
        name:String, website:String ->
        var result = 4 * 4
        println("$name owns $website")
    }
    lambdaMoreParams("karthiq", "chercher tech")
}

ENUMS in Kotlin

Parameters with lambda

Sometimes you might need to accept parameters for the lambda to perform some task and return the result.

Lambdas can accept parameters, still the lambda is enclosed with {} curly braces

Lambdas will have parameter as the first and then body, parameters and body are separated using -> symbol

Please do make sure, you do not have spaces between -> symbol.


fun main(args:Array<String>)
{
    var lambdaWithParameter = {name:String -> println("hello $name")}
    lambdaWithParameter("Moto")
}

Parameters are separated by comma if more than one parameters are present in lambda, also we can mentions parameters type using : symbol in kotlin lambdas.

Lambda Body can contains more than one line of code, everything will be considered as lambda block if it is in between { }


fun main(args:Array<String>)
{
    var lambdaMoreParams = {
        name:String, website:String -> println("$name owns $website")
    }
    lambdaMoreParams("karthiq", "chercher tech")
}

If you want to more crisper code or lesser code then you remove the data types of the parameters in the lambda because kotlin has a gift to interfere the type of the parameters.

But you need to specify the data types on the side of variable assignment as well as return type like var lambdaWithoutDataType:(String, String) -> Unit


fun main(args:Array<String>)
{
    var lambdaWithoutDataType:(String, String) -> Unit = {
        name, website ->
        println("my name is $name and i own $website")
    }
    lambdaWithoutDataType("karthiq", "chercher tech")
}

Sealed Classes in kotlin

Return value in lambda in kotlin

We can accept parameters, we can perform operations in lambda but you can also return values in in kotlin lambdas.

Last the statement in the lambda block will be considered as return value but it should not be a print statement or assignment operation.

If you want to return a value, then last line should evaluate into a value, return type will be inferred by kotlin compiler, so no need to specify return type.


fun main(args:Array<String>)
{
    var returnVauleLambda = { a:Int, b:Int ->
		println("Calculates the multiplication")
		a * b
    }
    println(returnVauleLambda(3, 4))
}

Kotlin Generics with Classes

Higher Order Functions in Kotlin

Higher order function is a function, which accepts not only value/variable as parameters but also accepts functions/lambdas as parameter. You can call a function as higher order functions if the functions return a function/lambda.

Higher order function either accept a function as parameter or return function as value or both

You can represent the function as values in kotlin either using lambdas or by using the function references.

Higher order function helps to code the program faster, and remove the code duplication and also simplifies the code.

Function types :

Please be aware that, this not about types of functions, this functions types, Function type is decided based on the value it returns.

Sometime back, you might have come across below program, the function type of below is (String, String) -> Unit.

What does function type denote in lambda ?
Function type denote the type of parameters accepted to the function by specifying them inside parentheses, and the return type separated by -> sign.

(String, String) -> Unit. (String, String) : accepts two parameters both are type of string.
Unit : return type of the function is Unit, when a function does not return anything then it is type of Unit


fun main(args:Array<String>)
{
    var lambdaWithoutDataType:(String, String) -> Unit = {
        name, website ->
        println("my name is $name and i own $website")
    }
    lambdaWithoutDataType("karthiq", "chercher tech")
}

Every lambda function will have a function type, that means lambda function must return something when you use it like above syntax.

Below function is type of ()-> String


fun main(args:Array<String>)
{
    var lambdaWithoutDataType:()-> String = { "hello" }
    println(lambdaWithoutDataType())
}

Kotlin's Function accepting function/lambda :

For accepting a function into another function, we pass the lambda/function as parameter, to the function like below. higher-order-function-syntax Before proceed further I want to clarify something which I had doubt for some years ( as i am working with typescript )

We pass functions as arguments (on calling a function) in other languages like java and python, kotlin so on, but there actually before calling the intended function the function in the argument becomes a value.


fun main(args:Array<String>)
{
	// receives string only not as function
    fun normalFunction(str:String){
        println("the string passed is : $str")
    }
    fun sayhello():String{
        return "hello"
    }
    normalFunction(sayhello()) // here itself the value will go as like below call
	// normalFunction("hello")
}

But when you pass the lambda as parameter the lambda function will not get executed before calling the lambda/function explicitly, inside the actual function we must invoke the lambda then only the lambda gets executed.

We have to invoke the lambda using invoke operator, which is nothing but () like below.


fun main(args:Array<String>)
{
    // sample fun accepts lambda as parameter
    fun sampleFun(lambdaFunction:(String )-> Unit) {
		println("till now lambda did not get call")
        // lambda invocation
        lambdaFunction("someText")
    }
	// passing lambda as argument
    sampleFun ({ str -> println(str) })
}

When you have only lambda as parameter, you can still minimize the code by removing the parentheses, like below


// passing lambda as argument and remove () of function
sampleFun { str -> println(str) }

You might have question that can i have other parameters lambda, obviously function can accept other parameter.

You can also perform task using lambda on the other parameters received along with lambda


fun main(args:Array<String>)
{
    // sample fun accepts lambda as parameter
    fun sampleFun(name:String, lambdaFun:(String )-> Unit, website:String) {
        // lambda invocation
        println("Received name as $name and website as $website")
		// hcet rehcrehc is reverse of chercher tech
        lambdaFun(website)
    }
    // lambda prints text in reverse
    sampleFun ("karthiq", { str -> println(str.reversed()) }, "chercher tech")
}

Type Inference in kotlin lambda :

In above example, I have used the lambda like { str -> println(str.reversed()) } in this line of code I have not mentioned the type of the str

Data Type is mandatory for function parameters but in case of lambdas kotlin is capable of inferring the type of the parameter. So I have not mentioned the type.


fun main(args:Array<String>)
{
    // sample fun accepts lambda as parameter
    fun sampleFun(name:String, lambdaFun:(String )-> Unit, website:String) {
        
        println("Received name as $name and website as $website")
		// lambda invocation
        lambdaFun(website)
    }
    // lambda prints text in reverse
    sampleFun ("karthiq", { str -> println(str.reversed()) }, "chercher tech")
	// lambda prints the length of the string
	sampleFun ("karthiq", { str:String -> println(str.length) }, "chercher tech")
}

it in kotlin lambdas :

it is used when we have only one parameter in lambda, so the it points to that single parameter.

using it we can access all the method and variables, just like using the parameter.


fun main(args:Array<String>)
{
    // sample fun accepts lambda as parameter
    fun sampleLambdaUsingIT(lambdaFun:(String )-> Unit) {
        // lambda invocation
        lambdaFun("Somebody please reverse me !!!")
    }
    // lambda prints text in reverse
    sampleLambdaUsingIT ({ println(it.reversed()) })
}

KClass in Kotlin Reflection

Anonymous functions in kotlin

An anonymous function looks very much like a regular function declaration, except that anonymous functions will not have name.

Its body can be either an expression (single line) or a block of code, anonymous function parameters are always passed inside the parentheses

Anonymous function in Kotlin allow you to specify return type, if you don't specify, then compiler will infer the type

In addition to that, return statement inside anonymous will exit only the function block.


fun main(args:Array<String>)
{
    var abc = fun(x: Int, y: Int): Int { // Int is return type
        return x + y
    }
    
    println(abc(4, 5))
}

Kotlin Map and Properties File

returns in lambdas and Anonymous functions

I hope, you do remember that last value will be considered as return value if not return is present, it is applicable only when last statement is a value and not an assignment operation, also function should not be having Unit type.

returns in standard functions :

When you have a return statement in function, the control exits from the function with given value.

If you have any statement after return will not be executed, some compilers will throw exception on compile time itself.


fun main(args:Array<String>)
{
	returnExample()
}
fun returnExample():String{
	println("first statement")
	return "abc"
	println("hello, probably they will ignore me :(")
}

returns from lambda :

The return statement inside the lambda will return from the current lambda, to have return statement in Lambda we have to label (name it) the lambda

Labeling a lambda is nothing but giving some name before the lambda separated with @

return statement in lambda will never exit the function which holds the lambda.


fun main(args:Array<String>)
{
    returnExample()
}
fun returnExample(){
    println("first statement")
    // lambda prints text in reverse
    var lambdaExpression = IamTheLabel@{ str:String ->
        println(str.reversed())
        return@IamTheLabel
        }
    lambdaExpression("Kotlin")
    println("I am a statement after the return statement in lambda")
}

return in Anonymous function :

return statement inside anonymous functions will exit only the anonymous function block.

fun main(args:Array<String>)
{
    returnExample()
}
fun returnExample(){
    println("first statement")
    // anonymous prints text in reverse
    var anonymousFunction = fun(x: Int, y: Int): Int { // Int is return type
        return x + y
        println("they will not print me as I am after return statement")
    }
    println(anonymousFunction(4, 5))
    println("I am a statement after the return statement in anonymous")
}

Read Excel in kotlin

Nested lambda in kotlin

We can have nested lambdas in kotlin, in below example lamb is outer lambda and thisIsNestedlambda is nested lambda.


fun main(args:Array<String>)
{
    var lamb = { str:String ->
        println("I am a lambda also I can Contain a Lambda")
        println("@@@@I received a value : $str @@@@")
        var thisIsNestedlambda = {
            println("****I am nested lambda****")
        }
        thisIsNestedlambda()
    }
    lamb("kotlin chercher tech")
}

Reading a CSV file with Header

kotlin lambdas with receivers

Lambdas with receivers are basically exactly the same as extension functions, they're just able to be stored in properties, and passed around to functions.


fun main(args:Array<String>)
{
    val str = buildString {
        append("Hello")
        append("****")
        append("Mars")
    }
    println(str)
}
fun buildString(actions: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.actions()
    return builder.toString()
}

  • Inside the lambda you pass to buildString you're in a new scope, you have new methods and properties available to use. In this specific case, you can use methods on the StringBuilder type without having to call them on any instance.
  • The actual StringBuilder instance these function calls are going to be made on is not managed by you - its up to the internal implementation of the function to create one and call your extension function on it.
  • It follows from the previous point that this function could do much more than just call the function you passed to it once - it could call it multiple times, on various StringBuilder instances, store it for later use, etc.

Interface in Kotlin

Variable Scope in Lambda

Sometimes the scope of the kotlin lambda/functions are also called as closure.

Scope of Function Parameters :

The scope of the function parameter are limited inside the functions, outside of that function you cannot access them.

Function always receives values, any changes on parameters will not reflect on the original arguments.

In kotlin, you cannot re-assign values of the parameters as they are formed using val internally.)


fun main(args:Array<String>)
{
    fun samepleFunction(name:String, website:String)
    {
        var abcLambda = {
            println("name value is : $name ")
        }
        abcLambda()
    }
    var originale_name = "karthiq"
    var original_website = "chercher tech"
    samepleFunction(originale_name, original_website)
    // un comment below line and try to execute,
    // you will face error
    /* println(name) */
}

Scope of Local variable declared inside functions :

The variable declared inside function can be accessed only inside the function. If there is nested function then nested function access the parameter declared the in outer functions.

Lambdas inside function also can access the variable inside the function and modify them. If any local variable is modified either in nested function or in lambda, will have the change effect through the outer function.


fun main(args:Array<String>)
{
    fun samepleFunction()
    {
        // local variable
        var dummyVariable = "KARTHIQ"
        // accesing iinside nested function
        fun nestedFucntion(){
            dummyVariable = "*******"
            println("changed the value to  : $dummyVariable")
        }
        // accessing inside the lambda
        var abcLambda = {
            println("value is : $dummyVariable ")
        }
        println("before all values changes : $dummyVariable")
        // calling the nested function
        nestedFucntion()
        // calling the lambda
        abcLambda()
        println("after all values changes : $dummyVariable")
    }
    samepleFunction()
	
	 // un comment below line and try to execute,
    // you will face error
	// accesing outside the function
    /* println(dummyVariable) */
}

Scope of variable declared inside Lambda :

The variable declared inside the lambda is only accessible inside that lambda, you cannot access it out side the lambda.


fun main(args:Array<String>)
{
    fun samepleFunction()
    {
        // accessing inside the lambda
        var abcLambda = {
            var lambdaLevelVaraiable = "chercher tech"
            println("value is : $lambdaLevelVaraiable ")
        }
        // calling the lambda
        abcLambda()
    }
    samepleFunction()
	
	 // un comment below line and try to execute,
    // you will face error
	// accesing outside the function
    /* println(dummyVariable) */
}

Late Init in Kotlin

Returning function from function

Returning a function from function is one of the feature of Higher order functions in kotlin, to return a function we need to specify function type as the return type.

Function accepting function is used more the function returning function in kotlin

syntax of functions returning function. functions-returning-function-lambda Sample code for a function returning a function/lambda


fun main(args:Array<String>)
{
    fun thisFunctionReturnFunction() : (String) -> String = {
        str -> str.toUpperCase()
    }
    // calling function which return a function.
    var sample = thisFunctionReturnFunction()
    println(sample("Tom cruise killed super man in MI:fallout"))
}

Kotlin Standard Functions

lambda accepting lambda

We can have lambda accepting a lambda, I am sorry about the super-natural alignment of the below program


fun main(args:Array<String>)
{
	var returnVauleLambda = { craziness:Int, lambdaCrazy:()->String ->
		println("craziness value is : $craziness");
		println("The string received in lambdaCrazy : ${lambdaCrazy()}");
	}
	returnVauleLambda(3,
	{
		println("Returning abc")
		return value
	})
}

While Loop in Kotlin

Kotlin with vararg

You cannot write a lambda with vararg, if you try, you will face un-resolved reference error.


fun main(args:Array<String>)
{
    var lambdaWithoutDataType:(varag ab:String, bbc:String) -> Unit = {
        name, website ->
        println("my name is $name and i own $website")
    }
    lambdaWithoutDataType("karthiq", "chercher tech")
}

invoke Operator

aaaaaaaaaaaaa
Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions

Recent Addition

new tutorial Selenium Online Training : Our next online training course for Selenium with Java starts from 17th December 2018.

You can attend first 3 classes for free, the total course fee is INR 10,000

The course time would be 8.00 PM(IST) for the first three classes

If you are interested to learn, then you can join the course by sending email to chercher.tech@gmail.com

or Register below


 
Join My Facebook Group
Join Group