🚀 · also() & apply()

2 min read · Updated on by

Read on for a description of the also() and apply() scope functions in Kotlin.

The also function

The definition of also is essentially this:


//sampleStart
inline fun <T> T.also(block: (T) -> Unit): T {
    block(this)
    return this
}
//sampleEnd
fun main() {
    val poem = """
        Kotlin, the architect of code's stronghold,
        With extension properties, it's a tale told.
        From towers to ramparts, a structure so grand,
        In the world of languages, it takes a stand!
    """.trimIndent()
    println(poem)
}

If this seems familiar, it is because you wrote your own version in a previous lesson.

From a purely practical standpoint, what this allows you to do is to execute a side-effect (i.e. a block of code that does not return anything = Unit) and then continue working with the receiver.

We talked about one possible use, which was logging information inside a longer call chain:


//sampleStart
val someOtherProp = obj.someProp.someMethod().also {
    log(it)
}.someOtherProp
//sampleEnd

You could easily get by just by declaring an extra variable:


//sampleStart
val someMethodResult = obj.someProp.someMethod()
log(someMethodResult)
val someOtherProp = someMethodResult.someOtherProp
//sampleEnd

However, not only does also save you some keystrokes, but in some situations can lead to more elegant code by compressing it into a single expression. That can come in handy when defining a function as an expression.

But don't forget - shorter/more concise is not always better! Prioritize readability over everything else.

The apply function

The definition of apply is essentially:


//sampleStart
inline fun <T> T.apply(block: T.() -> Unit): T {
    block()
    return this
}
//sampleEnd
fun main() {
    val poem = """
        Kotlin, the architect of code's stronghold,
        With extension properties, it's a tale told.
        From towers to ramparts, a structure so grand,
        In the world of languages, it takes a stand!
    """.trimIndent()
    println(poem)
}

When you compare apply with also, you'll come to the startling realization that they are practically identical - the only difference is that also uses the receiver as a parameter to block, while apply uses it as a receiver.

From a functional standpoint, the following are completely equivalent:


//sampleStart
class A {
    fun doStuff() {
        // Stuff
    }
}

A().also { it.doStuff() }

A().apply { doStuff() }
//sampleEnd

So when should you use which, and more importantly, why? Read on to find out.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

The Kotlin Primer