Kotlin Standard Functions: apply, also, let, with, and run

Kotlin has provided several powerful functions in Standard.kt. Let’s go through them here quickly.

apply()

The apply() function is an extension function on all types. When invoked, it calls the closure function passed in, and returns the receiver object. It makes things like builders cleaner, e.g:

data class Builder(var value: Int) {
  fun value(value: Int) = apply { this.value = value }
  // ...
}

also()

The also() function is similar to the apply() function, except that this is not shadowed, e.g.:

class MyClass {
  fun test() {
    val myString = "myString"
    myString.apply {
      // "this" is referencing "myString"
      // there's no "it" here
    }
    myString.also {
      // "this" is referencing "myClass"
      // "it" is referencing "myString"
    }
  }
}

let()

The let() function allows us to define a variable within the specific scope but not beyond. It makes the code self-contained, and prevents the variable from “leaking out”, e.g.:

val value = sqliteHelper.readableDatabase.let { db ->
  val cursor = db.query(...)
  return@let cursor.toValue()
}
// the opened database is no longer visible here

with()

The with() function makes it convenient to call multiple methods on the same (non-null) object, e.g.

with(view) {
  alpha = 0.0F
  visibility = View.VISIBLE
}

run()

The run() function is essentially a combination of let() and with(), so you can do things like this:

val value = sqliteHelper.readableDatabase.run {
  val cursor = query(...)
  return@let cursor.toValue()
}

That’s it! All these are just regular functions, but they can be easily combined to make the code nicer.