Kotlin - Scoped function

The Kotlin standard library contains several functions whose sole purpose is to execute a block of code within the context of an object.

On this page

Introducció

When you call a scoped function on an object with a lambda expression provided, it forms a temporary scope.

In this scope, you can access the object without its name. Such functions are called scope functions. There are five of them: let, run, with, apply, and also.

Basically, these functions all perform the same action: execute a block of code on an object. What’s different is how this object becomes available inside the block and what the result of the whole expression is.

Here’s a typical example of how to use a scope function:

Person("Alice", 20, "Amsterdam").let {
println(it)
it.moveTo("London")
it.incrementAge()
println(it)
}

If you write the same without let, you’ll have to introduce a new variable and repeat its name whenever you use it.

val alice = Person("Alice", 20, "Amsterdam")
println(alice)
alice.moveTo("London")
alice.incrementAge()
println(alice)

Scope functions don’t introduce any new technical capabilities, but they can make your code more concise and readable.

Due to the many similarities between scope functions, choosing the right one for your use case can be tricky. The choice mainly depends on your intent and the consistency of use in your project. Below, we provide detailed descriptions of the differences between scope functions and their conventions.

##Function selection

To help you choose the right scope function for your purpose, we provide this table that summarizes the key differences between them.

FunctionObject referenceReturn valueIs extension function
letitLambda resultYes
runthisLambda resultYes
runLambda resultNo: called without the context object
withthisLambda resultNo: takes the context object as an argument.
applythisContext objectYes
alsoitContext objectYes

Here is a short guide for choosing scope functions depending on the intended purpose:

  • Executing a lambda on non-nullable objects: let
  • Introducing an expression as a variable in local scope: let
  • Object configuration: apply
  • Object configuration and computing the result: run
  • Running statements where an expression is required: non-extension run
  • Additional effects: also
  • Grouping function calls on an object: with

The use cases of different scope functions overlap, so you can choose which functions to use based on the specific conventions used in your project or team.

Although scope functions can make your code more concise, avoid overusing them: it can make your code hard to read and lead to errors. We also recommend that you avoid nesting scope functions and be careful when chaining them because it’s easy to get confused about the current context object and value of this or it.