One Page

Let, Also, Run, Apply - Explained

July 25, 2019

Let’s see what a few kotlin extension functions do: let, also, run and apply

Each of them are just differ in two ways.

  1. The way the object that they’re called on, is passed in.

    a. A separate variable ‘it’

    b. We are inside the object, it can be referred to as ‘this’ or its functions can be called as if we’re writing them inside its class.

  2. What they return.

First a quick summary:

  • let -> gives ‘it’, returns anything
  • also -> gives ‘it’, returns the given object itself (mutations expected)
  • apply -> gives ‘this’ (you’re inside the class), returns the given object itself (mutations expected)
    1. run -> can operate as an independent block and return anything.
    2. run -> gives ‘this’, returns anything

Now let’s get into detail.

Let

definition: inline fun <T, R> T.let(block: (T) -> R): R

let -> gives ‘it’, returns anything

eg: val len : Int = "hello".let{ it.length }

definition: inline fun <T> T.also(block: (T) -> Unit): T

Also

also -> gives ‘it’, returns the given object itself (mutations expected)

definition: inline fun <T> T.also(block: (T) -> Unit): T

Likely useful when you want to perform a few operations on it and want it as a more useable variable. eg:

data class Dog(val name: String, var emotion: String? = null)

val dog = Dog("fluffy").also {
    it.emotion = if (it.name.startsWith("f")) "happy" else "ecstatic"
}

This would infact be better served by an apply, since we wouldn’t have to do it.name and could just do name.startsWith but it serves one example. (ideally even being done with a delegate on the name)

Run

definition 1:

inline fun <R> run(block: () -> R): R

run -> can operate as an independent block and return anything. Let’s assume that we have a cat and dog object, each with a walk method:

run { isCat? Cat() else Dog() }.walk()

and

definition 2:

inline fun <T, R> T.run(block: T.() -> R): R

run -> gives ‘this’, returns anything

eg: val len : Int = "hello".run{ this.length }

Apply

definition: inline fun <T> T.apply(block: T.() -> Unit): T apply -> gives ‘this’ (you’re inside the class), returns the given object itself (mutations expected) eg:

val intent: Intent = Intent().apply {
            setClassName("com.example", "com.example.MainActivity")
            action = Intent.ACTION_SEND
        }

Have suggestions for a topic I should cover? Send me a dm at @AniketSMK or email me at hello@[firstname][lastname].com


Aniket Kadam, author

Written by Aniket Kadam - building useful things. Follow me on Twitter