How to use Kotlin’s let and also functions.

When we have three functions that we want to run in sequence. We can easily do this on a list of inputs:

fun step1(input: Any): Any = TODO()
fun step2(input: Any): Any = TODO()
fun step3(input: Any): Any = TODO()

fun stepsList(list: List<Any>) =
    list.map(::step1)
        .map(::step2)
        .map(::step3)

Doing this on a single input is less straightforward.

We could make a oneliner. The functions have to be reversed. And it can be hard to read when the line gets long.

fun stepsSingle(input: Any) =
    step3(step2(step1(input)))

Or we could use intermediate variables.

This means we have to use the less convenient function notation with {} and return instead of =.

Also, it’s easy to make a mistake here by mixing up the variables.

fun stepsVal(input: Any): Any {
    val r1 = step1(input)
    val r2 = step2(r1)
    return step3(r2)
}

Using let we can chain the functions as comfortably as we did with map in the List:

fun stepsLet(input: Any) =
    input.let(::step1)
        .let(::step2)
        .let(::step3)

In the same way, we can use also to log results without changing the structure of our code:

fun stepsAlso(input: Any) =
    input.let(::step1)
        .let(::step2)
        .let(::step3)
        .also { println("stepsAlso result: $it") }

We can also use let to deal with nulls, comparable with map or fold in Scala:

    interface DbConf
    interface DbConnection
    object DummyDb : DbConnection
    fun createConnection(conf: DbConf): DbConnection = TODO()

    fun initDatabase(conf: DbConf?): DbConnection =
        conf?.let { createConnection(it) } ?: DummyDb
shadow-left