Scoping Functions

"Scoping functions" are amongst those "little" things I like very much about Kotlin and use frequently.

They offer an concise, elegant way to restrict the scope of variables in a useful way.


Often you write code that creates a new object and immediately sets some of its properties and/or calls methods on it.

So, in Java, such code might look like this:

Person person = new Person();

Thanks to Kotlin's properties, the same code becomes more concise:

val person = Person();

Even better it becomes using the scoping function apply:

val person = Person().apply {

This is apply's signature:

inline fun <T> T.apply(block: T.() -> Unit): T (source)

The function calls the given block with this as receiver and returns this as a result.

That means, within the block, you can access the object you called apply on (the receiver) using this. As usual, you can omit this, which makes the code so readable.

Even more, as apply returns this, we can assign the created and prepared instance to a variable in a single expression.

So, with apply, you can encapsulate the creation, preparation and assignment of an object in a single expression, leading to less redundancy and very readable code.

Let, run and also

Besides apply, there are some more, very similar, functions which differ in the way you access the caller/receiver within the block and in what the call as a whole returns.

it or this?

As described before, within the block of apply, you can access the original object using this (and, as usual drop this for better readability).

In addition to apply there is the also function, which differs in the way you access the calling object: instead of referring to it using this, the block is called with it as the single argument, hence you can refer to it using the it keyword:

val person = Person().also {

In contrast to this you cannot omit it, which makes also blocks a bit less readable. So I personally prefer apply over also, as long as I don't want to resolve some shadowing issues.

What about the returned value?

As seen, apply and also only differ in the way you access the calling object, either using this or it.

They both return the calling object.

But there are times you'd rather not return the calling object but the result of the called block.

That's what run and let are for.

They do not return the calling object but rather whatever the called block returns. Similar to apply and also, the difference between run and let is the way you access the calling object within the block (this or it).

The following table shows all the differences at glance:

Function Access to caller Returns
apply this caller (this)
also it caller (it)
run this block result
let it block result