In programming, a lambda expression is an anonymous function that’s written as an expression.
Since lambda is an expression, it can be passed as an argument to a function or as a return value of a function execution.
Many programming languages have their own lambda expression syntax. In Kotlin, a lambda expression syntax is as follows:
var [name] : [input type(s)] -> [output type] = { [arguments] -> [body] }
The syntax above may look confusing to you, so let’s see a valid example of a Kotlin lambda expression.
Consider the following makeUppercase()
function:
var makeUppercase : (String) -> String = { str -> str.uppercase() }
Now let me explain the above example.
The name of the lambda expression above is makeUppercase
.
The : (String) -> String
syntax means that the function accepts one input of type String
and returns a value of type String
as well.
The { str -> str.uppercase() }
syntax is the body of the lambda expression. In this case, the input parameter is named str
. You don’t need to explicitly declare the type of str
because it’s already declared in the [input type]
syntax.
The body of the expression simply calls the .uppercase()
method of the String
instance.
Now that you have a lambda expression defined, you can call the makeUppercase()
like any other function:
makeUppercase("nathan") // NATHAN
makeUppercase("sarah") // SARAH
A lambda expression requires a return type to be explicitly defined. When you want to return nothing, you can define the return type as Unit
.
var makeUppercase: (String) -> Unit = { str ->
println(str.uppercase())
}
When you need to define multiple parameters for your lambda expression, you can add the parameter types separated by a comma.
The following example creates a lambda expression that accepts 3 parameters: a String
, an Int
, and a Boolean
:
var myLambda: (String, Int, Boolean) -> Unit = { str, num, bool ->
println("$str $num $bool")
}
myLambda("nathan", 1, true) // nathan 1 true
Alternatively, you can move the input and output types definition of your lambda expression from the left side of the =
symbol to the right side as follows:
val makeUppercase = { str: String -> str.uppercase() }
In the example above, the argument type is defined as String
, while the return type is inferred from the lambda body.
The it
keyword
When your lambda expression contains only a single parameter, you can use the it
keyword to refer to that argument instead of the custom name you define.
Consider the following example:
val plusTwo : (Int) -> Int = { it + 2 }
plusTwo(4) // 6
In the plusTwo()
function above, the single input argument is referred as it
so you don’t need to define the argument list inside the curly brackets {}
.
The it
keyword will always refer to the single argument you passed into the function, so when it’s a String
, you can call String
methods on the keyword:
val makeUppercase : (String) -> String = { it.uppercase() }
Please keep in mind that when your lambda expression has more than one parameter, the it
keyword will throw an unresolved reference
error.
Writing the lambda expression outside the parentheses.
When you pass a lambda expression as the last argument of a function call, you can write the expression outside of the parentheses which contain the arguments.
For example, when creating an array using the Array
class constructor:
val myArray = Array(3) { i -> i * 2 }
// equals to
val myArray = Array(3, { i -> i * 2 })
Kotlin lambda with function pointers
Finally, when your lambda expression body is only a single function call, you can use the function pointers syntax (::
) to call that function instead of the normal .functionName()
call.
Take a look at the following example:
val makeUppercase: (String) -> String = String::uppercase
With function pointers, you can remove the curly brackets {}
and the lambda body becomes a single ::uppercase
call.
Kotlin lambda common examples
Kotlin lambda expressions are commonly used when you call a function that requires a function as its argument.
For example, the forEach
method used to iterate over a value accepts a lambda expression as follows:
val name = "Nathan"
name.forEach { c -> print(c) } // Nathan
A lambda expression is also expected when you call Array
methods like map
and reduce
:
val numbers = arrayOf(1, 2, 3)
val newNumbers = numbers.map { n -> n + 2 }
newNumbers.toString() // [3, 4, 5]
val aSum = numbers.reduce { accumulator, currentEl ->
accumulator + currentEl
}
aSum.toString() // 1 + 2 + 3 = 6
When you’re creating an Android application, you might also use a lambda expression for a listener body.
For example, here’s an Android Button
with its setOnClickListener
lambda expression:
val button = findViewById<Button>(R.id.my_button)
button.setOnClickListener {
Toast.makeText(this, "Hello", Toast.LENGTH_SHORT).show()
}
Now you’ve learned how lambda expressions work in Kotlin. Nice work! 👍