Author profile picture

let() (scope function)

Overview

The let() function is one of a handful of scope functions defined in the Kotlin standard library.

Example

val size = "Hello".let {
    println(it)
    it.length
}

In this example, the string “Hello” is printed, and then its length is assigned to the size variable.

Characteristics

When the let() extension function executes:

  • the receiver object that .let() is called upon is available as the lambda argument - by default, named it
  • the result of let() will be the result of the code block passed to it

Transformation

The let() method is frequently used to transform an object.

fun rotateLeft(it: String) = "${it.subSequence(1, it.length)}${it.first()}"

"greetings".let { rotateLeft(it) }

Of course, you can also use a function reference, which would make more sense in this example.

"greetings".let(::rotateLeft)

Alternatives

Transformation to members

If you’re transforming an object into one of its properties or the result of one of its functions, there’s no need for let() - just access the properties or functions directly.

// Unnecessary
"greetings".let { it.length }
"greetings".let { it.toUpperCase() }

// Preferred
"greetings".length
"greetings".toUpperCase()

Using extension methods

In cases where you’ve got a transformative function (such as rotateLeft() above), you might prefer to craft it as an extension function:

fun String.rotateLeft() = "${this.subSequence(1, this.length)}${this.first()}"

"greetings".rotateLeft()

This gives us the same characteristics as the direct property/function access discussed above (in the Transformation to members section) – meaning there’d be no need for the let() call – and it handles nulls more elegantly by allowing you to use a safe-call operator, like this:

var maybeGreetings: String? = null
maybeGreetings?.rotateLeft()

Comparison with map()

If you come from a Java 8 background, you might be familiar with the .map() function on Stream and Optional. Be careful not to confuse Kotlin’s let() with Kotlin’s map().

  • map() - similar to Stream.map(). It operates on the items in a collection.
  • let() - similar to Optional.map(). It operates on the object itself. If the object is a collection, then let() affects the collection as a whole, not the individual items in the collection.

More Alternatives

Choosing from among the different scope functions can be confusing. Check out the guide, Understanding Kotlin’s let(), also(), run(), and apply() for information on which function to pick.

Share this article: