lesson 38 – Lambda expressions in Kotlin language

lesson 38 – Lambda expressions in Kotlin language

Hello viewer, You can now have our Tutorial Lessons in your android mobile device and read it offline.
Download kotlin Programming APP on PlayStore
Download Website SEO Lessons APP on PlayStore

A lambda expression is when we send an anonymous function directly to a higher-order function.

It is more common to send a lambda expression instead of sending the reference of a function as we saw in the previous concept.

Problem 1

Define a higher order function called operate. They arrive as a parameter two integers and a function. In the function block call the function that arrives as a parameter and send the first two parameters.

From the main function call to operate and send different lambda expressions that allow adding, subtracting and raising the first value to the second.

Project149 – Principal.kt

fun operate (v1: Int, v2: Int, fn: (Int, Int) -> Int): Int {
    return fn (v1, v2)
}

fun main (parameter: Array <String>) {
    val sum = operate (2, 3, {x, y -> x + y})
        println (sum)
        val subtract = operate (12, 2, {x, y -> x - y})
            println (subtract)
    
            var Raisefourth = operate (2, 4, {x, y ->
                var value = 1
                for (i in 1..y)
                    value = value * x
                value
            })
            println (Raisefourth)
        }

The higher order function operate is the one we saw in the previous concept:

Fun operate(v1: Int, v2: Int, fn: (Int, Int) -> Int): Int {
    Return fn (v1, v2)
}

The first lambda expression we can identify it in the first call to the operate function:

    Val sum = operate (2, 3, {x, y -> x + y))
    Println (sum)

A lambda expression is composed of a series of parameters (in this case x and y), the sign -> and the body of a function:

{X, y -> x + y}

As we can check all lambda expression is enclosed in braces.

We can indicate the data type of the parameters of the function but usually do not have them:

Val sum = operate (2, 3, {x: Int, y: Int -> x + y})

The name of the parameters are called x and y, but could have any name:

    Val sum = operate (2, 3, {value1, value2: Int -> value1 + value2})

Always indicate the type of data that the function returns, in this case, it returns an Int that we indicate after the two points. If no data is returned, the function is set to Unit.

The algorithm of the function is expressed after the sign ->

X + y

It follows that the sum of x and y is the value to be returned.

The second call to operate we passed a lambda expression similar to the first call:

    Val subtract = operate (12, 2, {x, y -> x - y))
    Println (subtract)

The third call to operate we pass a lambda expression that in its algorithm we proceed to raise the first value according to the data that arrives in the second value:

    Var Raisefourth = operate (2, 4, {x, y ->
        Var value = 1
        For (i in 1..y)
            Value = value * x
        value
    })

Within the lambda expression, we can implement a more complex algorithm as it is in this case where we raise the parameter x to the indicated exponent with y.

It is important to note that the higher order function receives as a parameter a function with two parameters of type Int and returns an Int:

Fn: (Int, Int) -> Int

The lambda expression must pass a function with the same structure, i.e two integer parameters and return an integer:

{X, y ->
        Var value = 1
        For (i in 1..y)
            Value = value * x
        value
    }

We can identify the two parameters x and y, and the value that returns is the indicated data after the for.

A last change that we will implement to our program is that when a lambda expression is the last parameter of a function we can indicate the expression lambda after the parentheses so that the code of our program is more readable:

Fun main (parameter: Array <String>) {
    Val sum = operate (2, 3) {x, y -> x + y}
    Println (sum)
    Val subtract = operate (12, 2) {x, y -> x - y}
    Println (subtract)
    Var Raisefourth= operate (2, 4) {x, y ->
        Var value = 1
        For (i in 1..y)
            Value = value * x
        value
    }
    Println (Raisefourth)
}

The most common is to use this syntax to pass a lambda expression when it is the last parameter of a function.

Problem 2

Make a higher-order function that receives an array of integers and a function with an Int-like parameter and returns a Boolean.

The function must analyze each element of the array by calling the function it receives as a parameter, if it returns a true it is shown the element.

In the main function, define an array of 10-element integers and store random values between 0 and 99.

Print of the arrangement:

  • Multiple values of 2
  • Multiple values of 3 or 5
  • Values greater than or equal to 50
  • Values between 1 and 10, 20 and 30, 90 and 95

Project150 – Principal.kt

fun printIf (array: IntArray, fn: (Int) -> Boolean) {
    for (element in array)
        if (fn (element))
            print ("$element")
    println ()
}

fun main (parameter: Array <String>) {
    val array1 = IntArray (10)
    for (i in array1.indices)
        array1 [i] = ((Math.random () * 100)). toInt ()
    println ("Print multiple values ​​of 2")

    printIf (array1) {x -> x% 2 == 0}
    println ("Print multiple values ​​of 3 or 5")
    printIf (array1) {x -> x% 3 == 0 || x% 5 == 0}
    println ("Print values ​​greater than or equal to 50")
    printIf (array1) {x -> x >= 50}
    println ("Print values ​​between 1 and 10, 20 and 30, 90 and 95")
    printIf (array1) {x -> when (x) {
        in 1..10 -> true
        in 20..30 -> true
        in 90..95 -> true
        else -> false
    }}
    println ("Print all values")
    printIf (array1) {x -> true}
}

The higher order function PrintSi receives an array of integers and a function:

Fun printIf (array: IntArray, fn: (Int) -> Boolean) {

Within the function we run the array of integers and call the function that receives as a parameter for each element of the array, if it returns a true we will show the value:

    For (element in array)
        If (fn (element))
            Print ("$element")
    Println ();
}

The advantage of the print function is that we can use it to solve a large number of problems, we just have to pass a lambda expression that analyzes every integer it receives.

In the main function we create the array of 10 integers and load 10 random values between 0 and 99:

Fun main (parameter: Array <String>) {
    Val array1 = IntArray (10)
    For (i in array1.indices)
        Array1 [i] = ((Math.random () * 100)). ToInt ()

To print the multiple values of 2 our lambda expression receives as parameter an Int called xy and the algorithm that verifies whether it is even or not consists of verifying if the remainder of dividing by 2 is zero:

    Println ("Print multiple values ​​of 2")
    PrintIf (array1) {x -> x% 2 == 0}

It is important to understand that our lambda expression does not have a repetitive structure, but from the print function, it will call this anonymous function as many times as the elements have the array.

The algorithm of the function varies if we want to identify if the number is a multiple of 3 or 5:

    Println ("Print multiple values ​​of 3 or 5")
    PrintIf (array1) {x -> x% 3 == 0 || X% 5 == 0}

To print all values greater than or equal to 50 we must verify if the parameter x is> = 50:

    Println ("Print values ​​greater than or equal to 50")
    PrintIf (array1) {x -> x> = 50}

To analyze if the component is in different ranges we can use the when statement:

    Println ("Print values ​​between 1 and 10, 20 and 30, 90 and 95")
    Var cant = 0
    PrintIf (array1) {x -> when (x) {
        In 1..10 -> true
        In 20..30 -> true
        In 90..95 -> true
        Else -> false
    }}

In very simple form if we want to print the whole array we return for each element that analyzes our expression lambda the value true:

    Println ("Print all values")
    PrintIf (array1) {x -> true}

This is a problem where we can already notice the potentialities of the higher order functions and the lambda expressions that we pass to them.

Acotaciones

We said that one of the principles of Kotlin is to write concise code, for this when we have a lambda expression whose function receives a single parameter we can obviate it, including the sign ->
Then by convention that single parameter we can refer to it with the word ” Item”

Then our definitive program should be written with the following syntax:

Project150 – Principal.kt

fun printIf (array: IntArray, fn: (Int) -> Boolean) {
    for (element in array)
        if (fn (element))
            print ("$element")
    println ();
}

fun main (parameter: Array <String>) {
    val array1 = IntArray (10)
    for (i in array1.indices)
        array1 [i] = ((Math.random () * 100)). toInt ()
    println ("Print multiple values ​​of 2")
    printIf (array1) {it% 2 == 0}
    println ("Print multiple values ​​of 3 or 5")
    printIf (array1) {it% 3 == 0 || it% 5 == 0}
    println ("Print values ​​greater than or equal to 50")
    printIf (array1) {it >= 50}
    println ("Print values ​​between 1 and 10, 20 and 30, 90 and 95")
    printIf (array1) {when (it) {
        in 1..10 -> true
        in 20..30 -> true
        in 90..95 -> true
        else -> false
    }}
    println ("Print all values")
    printIf (array1) {true}
}

Keep in mind that when we call from the function printSi:

        If (fn (element))

The lambda expression receives a parameter called by default “it” and stores the passed value “element”:

    PrintIf (array1) {it% 2 == 0}

Problem 3

Create a higher-order function that receives a String and a function with a parameter of type Char and returns a Boolean.

The function must analyze each element of the String by calling the function it receives as a parameter, if it returns a true, it adds that character to the String that will be returned.

In the main function define a String with any string.

Call the higher order function and pass lambda expressions to filter and generate another String with the following restrictions:

  • A String with only the vowels
  • A string with only lowercase characters
  • A String with all non-alphabetic characters

Project151 – Principal.kt

fun filter (chain: String, fn: (Char) -> Boolean): String
{
    val cad = StringBuilder ()
    for (he in chain)
        if (fn (he))
            cad.append (he)
    return cad.toString()
}

fun main (parameter: Array <String>) {
    val chain = "Is this test 1 or test 2?"
    println ("Original String")
    println (chain)

    val result1 = filter (chain) {
        if(it == 'a' || it == 'e' || it == 'i' || it == 'o' || it == 'u' ||
                it == 'A' || it == 'E' || it == 'I' || it == 'O' || it == 'U')
        true else false
    }

    println ("Vocals only")
    println (result1)
    var result2 = filter (chain) {
        if (it in 'a' .. 'z')
            true
        else
            false
    }
    println ("Lowercase characters only")
    println (result2)
    var result3 = filter (chain) {
        if (it !in 'a'..'z' && it !in 'A'..'Z')
        true else false
    }
    println ("Non-alphabetic characters only")
    println (result3)
}

Our higher order function is called filtering and receives a String and a function:

Fun filter (String: String, fn: (Char) -> Boolean): String

The function that receives has a parameter of type Char and returns a Boolean.

The algorithm of the filter function consists of traversing the String that arrives as a parameter and calling the function fn that is the one that will inform if the analyzed character must be part of the final String to return.

By means of an object of class StringBuilder we store the characters to return, before returning we extract as String the contents of StringBuilder:

    Val cad = StringBuilder ()
    For (he in chain)
        If (fn (it))
            Cad.append (it)
    Return cad.toString ()

In the main function we define a String with any string:

Fun main (parameter: Array <String>) {
    Val chain = "Is this test 1 or test 2?"
    Println ("Original String")
    Println (chain)

The first call to the higher order function is done by sending a lambda expression that considers part of the String to generate only the lowercase and uppercase vowels:

    Val result1 = filter (string) {
        If it == 'a' || it == 'e' || it == 'i' || it == 'o' || it == 'u' ||
            It == 'A' || It == 'E' || It == 'I' || It == 'O' || It == 'U')
            True
        Else
            False
    }
    Println ("Vocals only")
    Println (result1)

Recall that we use “it” since the anonymous function has a single parameter and allows us to express a more concise code, in the long form should be:

    Val result1 = filter (string) {car ->
        If (car == 'a' || car == 'e' || car == 'i' || car == 'o' || car == 'u' ||
            Car == 'A' || Car == 'E' || Car == 'I' || Car == 'O' || Car == 'U')
            True
        Else
            False
    }
    Println ("Vocals only")
    Println (result1)

To generate a String with only the uppercase letters we must verify if the parameter of the anonymous function is in the range ‘a’ .. ‘z’:

    Var result2 = filter (string) {
        If (it in 'a' .. 'z')
            True
        Else
            False
    }
    Println ("Lowercase characters only")
    Println (result2)

Finally to recover all the symbols that are not letters we express the following condition:

    Var result3 = filter (string) {
        If it in 'a'..'z' && it !in 'A'..'Z')
            True
        Else
            False
    }
    Println ("Non-alphabetic characters only")
    Println (result3)

With this problem, we can continue to appreciate the great advantages provided by lambda expressions for solving algorithms.

About The Author

Related posts

Leave a Reply