Lambdas and anonymous functions in Kotlin
In this article I want to focus on how we could shrink the code by using lambda expressions.
Lambdas are functions used as data so, starting from Java 8, they can be passed to another function as a parameter. On the other hand, anonymous functions are functions that has no name. Let see how they look in Kotlin.
val strings = Arrays.asList("Lambda ", "expressions ", "are ", "cool")
I have declared a list of strings, and now I want to print them all on the console. I can do the same thing in two different ways.
Using anonymous function
strings.forEach(fun(s: String): Unit { print(s); return Unit })
I am using forEach method which accepts a function as parameter, and that function is an anonymous function. Its return type is Unit, which means literally “nothing”. I can remove the unnecessary parts of the code and shrink it a little bit.
strings.forEach(fun(s: String) { print(s) })
Now it looks more pretty! But wait, the variable type can be inferred.
strings.forEach(fun(s) { print(s) })
And now it is fabulous!! But it can be prettier using lambda expressions or simply lambdas.
Using lambda expressions
strings.forEach{ s: String -> print(s); Unit }
Very well! This is a lambda expression which is passed as data to forEach method. It’s a sort of translation of the first anonymous function into a lambda expression. I can shrink it as I have done before.
strings.forEach{ s: String -> print(s)}
It’s not bad, just remove the String type specification.
strings.forEach{ s -> print(s)}
And now it’s identical to the last anonymous function. But thanks to Kotlin you can go further with code shrinking.
strings.forEach { print(it) }
Almost perfect! The keyword it refers to the single parameter that forEach function passes to the lambda expression, so it makes sense to use it only if we have one parameter. For more info about it, please take a look here: https://kotlinlang.org/docs/reference/lambdas.html#it-implicit-name-of-a-single-parameter
While you check the link, I make some magic!
strings.forEach(::print)
Wow! That’s what I call “code minimalism”. The “::” symbol is the syntax for method references. What does it do? It simply tells Kotlin compiler that the print function is passed as a parameter. And ::print is a value of function type (String) -> Unit. So the compiler will not throw any error. More info can be found here: https://kotlinlang.org/docs/reference/reflection.html#callable-references
Like I say, lambdas are very cool and they can make your code more expressive and easier to read. Not sure? Just look at this comparison. Note that each line does the exact same thing.
strings.forEach(fun(s: String): Unit { print(s); return Unit })
strings.forEach { s: String -> print(s); Unit }
strings.forEach(fun(s: String) { print(s) })
strings.forEach { s: String -> print(s) }
strings.forEach(fun(s) { print(s) })
strings.forEach { s -> print(s) }
strings.forEach { print(it) }
strings.forEach(::print)