Kotlin — The power of lambdas

Alejandro Moya
Codelitt

--

In my previous post I explained how to replace listeners with lambdas, but didn’t talk too much about lambdas themselves. Today i’ll talk about a couple of things that make kotlin lambdas really powerful.

You’ll see lambdas in many places in kotlin, (not just as in a listener replacement), as many instructions rely on lambdas for fulfilling their purpose.

Lambdas are an anonymous portion of logic that are executed when they are required, which are commonly referred to as a block (which is how i’ll refer to them from now on).

  • A block is a function literal, with its own type, this means we can store them as properties
var myBlock: (Int) -> Unit = … 
  • A block could be optional as any other property in kotlin
var myBlock: ((Int) -> Unit)? = null 
  • A block body infers parameters and return types based on context and the last execution line
var myBlock: (Int) -> String = { theInt -> theInt.toString() }
var myBlock = { theInt: Int -> theInt.toString() }
  • A block body with a single parameter doesn’t need to have it named, instead you can access the values with the default name it
var myBlock: (Int) -> String = { it.toString() } 
  • A block with a parameter of the types Pair or Map could split the elements in it’s body declaration(since kotlin 1.1)
var myBlock: (Pair<*,*>) -> Unit = { firstValue, secondValue -> … } 
var myBlock: (Pair<*,*>, Int) -> Unit = { (firstValue, secondValue), intValue -> … }

With these basic concepts you can start creating your own blocks, so let’s dive a little bit deeper.
As I mentioned previously, blocks infer the return value and they ALWAYS have a return value, which means that any instruction that uses a block will return a result value.Lambdas are everywhere in kotlin, an if else uses blocks, when also uses blocks and they benefit from this, cause they can return a value.

var result = if (value > 10) “more than 10” else “less than 10”

or

var result = (if (value > 10) “more” else “less”) + “ than 10” 

in a when statement things get more interesting as each case has its own block and the value being checked is casted for you automatically.

var anyValue: Any = 7 //note that we are specifying the type as Anyvar result = when(anyValue) {
is Int -> { “${anyValue.toString()} is integer” }
is Double -> { “${anyValue.toString()} is double” }
is String -> { “$anyValue is string” }
else -> { “we don’t know the type of anyValue” }
}

This is extra powerful when using sealed classes, which are like enums on steroids, you can check for the different types in a when statement and have them casted to the one you need, after that you can access the state of the element you checked

sealed class MyPowerClass
data class DataFromCodelitt(val remote: Map<String, Any>?, val received: Boolean): MyPowerClass()
data class LocalData(val local: Map<String, Any>): MyPowerClass()
val result = when(data){
is DataFromCodelitt -> if(received) data.remote?.toString() else
“no data”
is LocalData -> data.local.toString()
}

--

--

Alejandro Moya
Codelitt

Mobile developer, Father, geek, this is my first attempt at having a blog, be kind 😄