Scope Functions - Kotlin Documentation
Scope Functions - Kotlin Documentation
html#let
v2.0.21
Solutions Docs Community Teach Play
The Kotlin standard library contains several functions whose sole purpose is to
execute a block of code within the context of an object. When you call such a
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
. 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.
1 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
If you write the same without let , you'll have to introduce a new variable and repeat
its name whenever you use it.
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.
To help you choose the right scope function for your purpose, we provide this table
that summarizes the key differences between them.
2 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
Here is a short guide for choosing scope functions depending on the intended
purpose:
3 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
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 .
Because scope functions are similar in nature, it's important to understand the
differences between them. There are two main differences between each scope
function:
Inside the lambda passed to a scope function, the context object is available by a
short reference instead of its actual name. Each scope function uses one of two ways
to reference the context object: as a lambda receiver ( this ) or as a lambda
argument ( it ). Both provide the same capabilities, so we describe the pros and
cons of each for different use cases and provide recommendations for their use.
4 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
// this
str.run {
println("The string's length: $length")
//println("The string's length: ${this.length}") // does the same
}
// it
str.let {
println("The string's length is ${it.length}")
}
}
run , with , and apply reference the context object as a lambda receiver ‐ by
keyword this . Hence, in their lambdas, the object is available as it would be in
ordinary class functions.
In most cases, you can omit this when accessing the members of the receiver
object, making the code shorter. On the other hand, if this is omitted, it can be hard
to distinguish between the receiver members and external objects or functions. So
having the context object as a receiver ( this ) is recommended for lambdas that
mainly operate on the object's members by calling its functions or assigning values to
properties.
In turn, let and also reference the context object as a lambda argument. If the
5 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
argument name is not specified, the object is accessed by the implicit default name
it . it is shorter than this and expressions with it are usually easier to read.
However, when calling the object's functions or properties, you don't have the object
available implicitly like this . Hence, accessing the context object via it is better
when the object is mostly used as an argument in function calls. it is also better if
you use multiple variables in the code block.
val i = getRandomInt()
println(i)
val i = getRandomInt()
println(i)
6 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
You should consider carefully what return value you want based on what you want to
do next in your code. This helps you to choose the best scope function to use.
The return value of apply and also is the context object itself. Hence, they can be
included into call chains as : you can continue chaining function calls on
the same object, one after another.
They also can be used in return statements of functions returning the context object.
val i = getRandomInt()
7 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
let , run , and with return the lambda result. So you can use them when
assigning the result to a variable, chaining operations on the result, and so on.
Additionally, you can ignore the return value and use a scope function to create a
temporary scope for local variables.
To help you choose the right scope function for your use case, we describe them in
detail and provide recommendations for use. Technically, scope functions are
interchangeable in many cases, so the examples show conventions for using them.
• is available as an argument ( it ).
8 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
let ↗ can be used to invoke one or more functions on results of call chains. For
example, the following code prints the results of two operations on a collection:
With let , you can rewrite the above example so that you're not assigning the result
of the list operations to a variable:
If the code block passed to let contains a single function with it as an argument,
you can use the method reference ( :: ) instead of the lambda argument:
let is often used to execute a code block containing non‐null values. To perform
actions on a non‐null object, use the safe call operator ?. on it and call let with
the actions in its lambda.
9 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
You can also use let to introduce local variables with a limited scope to make your
code easier to read. To define a new variable for the context object, provide its name
as the lambda argument so that it can be used instead of the default it .
We recommend using with for calling functions on the context object when you
don't need to use the returned result. In code, with can be read as "
"
10 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
You can also use with to introduce a helper object whose properties or functions
are used for calculating a value.
run is useful when your lambda both initializes objects and computes the return
value.
11 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
port = 8080
query(prepareRequest() + " to port $port")
}
You can also invoke run as a non‐extension function. The non‐extension variant of
run has no context object, but it still returns the lambda result. Non‐extension run
lets you execute a block of several statements where an expression is required. In
code, non‐extension run can be read as "
"
Regex("[$sign]?[$digits$hexDigits]+")
}
12 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
As apply ↗ returns the context object itself, we recommend that you use it for code
blocks that don't return a value and that mainly operate on the members of the
receiver object. The most common use case for apply is for object configuration.
Such calls can be read as " "
Another use case for apply is to include apply in multiple call chains for more
complex processing.
• is available as an argument ( it ).
also ↗ is useful for performing some actions that take the context object as an
argument. Use also for actions that need a reference to the object rather than its
properties and functions, or when you don't want to shadow the this reference
from an outer scope.
13 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
In addition to scope functions, the standard library contains the functions takeIf ↗
and takeUnless ↗. These functions let you embed checks of an object's state in call
chains.
When called on an object along with a predicate, takeIf returns this object if it
satisfies the given predicate. Otherwise, it returns null . So, takeIf is a filtering
function for a single object.
takeUnless has the opposite logic of takeIf . When called on an object along
with a predicate, takeUnless returns null if it satisfies the given predicate.
Otherwise, it returns the object.
14 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
displaySubstringPosition("010000011", "11")
displaySubstringPosition("010000011", "12")
For comparison, below is an example of how the same function can be written
without using takeIf or scope functions:
15 of 16 11/20/24, 23:53
Scope functions | Kotlin Documentation https://kotlinlang.org/docs/scope-functions.html#let
displaySubstringPosition("010000011", "11")
displaySubstringPosition("010000011", "12")
16 of 16 11/20/24, 23:53