Kotlin let (and other scoped functions)

Kotlin let (and other scoped functions)

Kotlin has many unique language features for someone coming from Java. One of the small but loved is the scoped functions.

If you read some Kotlin code before you probably already seen them. You may even use them without knowing exactly the differences between them.

All of them serve the same purpose: create a section of code where the code executed refers to an object. These are great because in Java you would have to declare a temporary variable to modify an object before returning it.

I am talking about let, run, with, apply and also. The differences between them:

  • What is returned
  • How the object is referenced inside the scoped function

To make it easier here is a table with all the combinations:

Scoped function Returns Object reference
let lamda result it
run lambda result this
with lambda result this
apply object this
also object it

A more practical way to group these methods (for hopefully remember using them when needed) is by use-case.

Since apply and also return the object itself, they are useful for object configuration and building.

val adam = Person("Adam").apply { 
    age = 20
    city = "London"
}
println(adam)
fun getRandomInt(): Int {
    return Random.nextInt(100).also {
        writeToLog("getRandomInt() generated value $it")
    }
}

For having additional effects or grouping function calls on an object use let, run, with.

val numbers = mutableListOf("one", "two", "three", "four", "five")
numbers.map { it.length }.filter { it > 3 }.let { 
    println(it)
} 
val service = MultiportService("https://example.kotlinlang.org", 80)

val result = service.run {
    port = 8080
    query(prepareRequest() + " to port $port")
}
val numbers = mutableListOf("one", "two", "three")
with(numbers) {
    val firstItem = first()
    val lastItem = last()        
    println("First item: $firstItem, last item: $lastItem")
}

But what about this and it? The practical difference is that when passing the object as an argument (i.e. with it) you are allowed to give a custom name for the object inside the context function.

Like with every language "trick", you should be careful not to overdo it. Otherwise, a feature that was designed to write more readable and concise code will have the opposite effects (e.g. if you start nesting these functions too much you might be confused where it or this refers to).

For more details on the subject, read the excellent official documentation on the feature.

Show Comments