Scoped Functions
The Kotlin standard library is full of scope functions that allow you to perform any given logic in the scope of an object, without referencing the object by its name. These functions allow for concise code, because it reduces a lot of the verbosity you'd have if you attempted to do similar operations in a language like Java. Whether you're starting out with Kotlin, or have been using it for awhile, it can be hard to remember all the scope functions.
this
or it
?
In most object oriented programming languages, Kotlin included, there's a concept of this
in regards to an object's self. Kotlin's technical name in scope functions you access the object as a lambda receiver (this
), or as a lambda argument (it
). The functions apply
, run
and with
all perform actions on a object as a lambda receiver (this
), with let
and also
use a lambda argument (it
).
We'll show exactly how this works with an example about pets. Here's a data class of a pet and our starting pet named Ajax is 4 years old. All these examples show how to update Ajax's age using the different scope functions. For these examples we'll explicitly specify the return type to highlight the difference between each function.
Returning the Scoped Object
We'll look at apply
first. Notice that the age
field is being access directly. That's because no matter what happens inside the lambda, the result will always be the pet object. This happens because apply
references the pet
object as a lambda receiver (this
).
also
behaves similarly. Except we reference pet
as a lambda argument (it
).
Those are the only two that always return pet object we initially referenced.
Returning the Lambda Result
The scope functions run
, with
, and let
all return the result of the lambda.
With let
we reference a lambda argument (it
) as well, but you can see the return type is different. That's because the return type is now the lambda result. As you can see the assignment of age
to 5 doesn't return anything so pet will be of type Unit
. You can see in the second example, the return type changes base on the return type of the final line of the lambda.
That behavior is like run
except it uses a lambda receiver (this
).
run
also has a second functionality, where you can use it stand alone.
Then there is with
. It behaves like the first run
example. It references this
and returns the lambda result. It's different because it takes the pet
object as an argument for the function.
As you can see they all operate differently, but you can use a few interchangeably. Here's how you could rewrite the first run
example using let
.
There aren't hard and fast rules on when you should one or another. In the end it can come down to personal preference. As someone who codes Kotlin everyday, of these scope functions, I use let
, apply
, and also
the most.
Here's a diagram to save and reference.
If you like what you've read, want to continue the discussion, or have anything else on your mind, reach out to me on Twitter with your favorite scope function.