Kotlin Scope Functions: Common Usage

Vinay Joglekar
Aug 13 · 4 min read
Image for post
Image for post
Photo by Marc Reichelt on Unsplash

One of the main reasons developers are attracted to kotlin is how concise it is to write. Scope functions are one of the ways to write such concise code. According to the official documentation:

The scope functions do not introduce any new technical capabilities, but they can make your code more concise and readable.

The standard or scope functions that are provided by the language are let, run, apply, also, with.

Scope functions execute a block of code for a particular object within its context using a lambda expression. But, it's not just about writing less code.


To use these functions, we must understand couple of things.

1. ‘this’ and ‘it’

Inside a lambda of a scope function, this (lambda receiver) is used to access the context object. The same object can be accessed by using it (lambda argument). In general, both can perform similar things.

this

run, apply, with use ‘this’ to access the context object. General rule of thumb is

Having the context object as a receiver ‘this is recommended for lambdas that mainly operate on the object members: call its functions or assign properties.

it

let and also use ‘it’ to access the context object. Instead of ‘it’, we can also provide custom name.

Having the context object as ‘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.

2. Result

The behaviour of scope functions can also be differentiated on the basis of their return values. There are two things to remember:

  1. apply and also return the context object.
  2. let, run, and with return the lambda result.

Now, I will try to explain the most common practical usages of the functions.

1. let

When should we use let function? Well, there are several scenarios. Most common scenario is null check. How did we usually write null checks?

if(person!=null) {
print(person.name);
}

With let it looks simpler :

person?.let{
print(it.name)
}

Another common and practical usage is on result of call chains. Suppose we have list of people and we need to print names of people whose age is greater than 25. We might write something like this :

data class Person(val name: String, val age: Int)

fun coolFunction() {
val persons = mutableListOf(
Person("Vinay", 29),
Person("Manish", 30),
Person("Kunal", 24)
)
val resultList = persons.filter { it.age > 25 }.map { it.name }
println(resultList)
}

let simplifies it in this way :

data class Person(val name: String, val age: Int)

fun coolFunction() {
val persons = mutableListOf(
Person("Vinay", 29),
Person("Manish", 30),
Person("Kunal", 24)
)
persons.filter { it.age > 25 }.map { it.name }.let {
println(it)
}
}

Note: This is very simple example of chaining for easier understanding. It is more helpful in real life where there is bit of complexity in chaining.

2. run

run is useful when we initialise an object and perform some operation on that object. All this is done within a single run block. re-scopes the variable it’s used on to. The last expression returns a result.

val lengthOfName = Person("Vinay", 29).run {
println("Age is $age")
println("Name is $name")
name.length
}
print(lengthOfName)

3. apply

Common use case of apply is object configuration. Below code comparison is self explanatory.

val dialog = CustomDialogFragment(this)
dialog.setCanceledOnTouchOutside(false)
dialog.setMessage("Do you want to cancel this transaction?")
dialog.setPositiveButton("Yes")
dialog.setNegativeButton("No")

if we use apply for configuration of dialog object :

val dialog = CustomDialogFragment(this)
dialog.apply {
setCanceledOnTouchOutside(false)
setMessage("Do you want to cancel this transaction?")
setPositiveButton("Yes" )
setNegativeButton("No" )
}

Looks cleaner. Doesn’t it? We don’t have to write “dialog.” again and again.

4. also

Common use of also is for side effects without modifying the object. We can use it for doing some operation on intermediate result. also does not transform the object. It returns same object.

As per the official document :

When you see also in the code, you can read it as “and also do the following with the object.

val persons = mutableListOf(
Person("Vinay", 29),
Person("Manish", 30),
Person("Kunal", 24)
)
val mappingResult = persons.map { it.name }
println(mappingResult)
val filteredResult = mappingResult.filter { it.length > 5 }
println(filteredResult)

By using apply, it looks much cleaner, no need to break the chain!

val persons = mutableListOf(
Person("Vinay", 29),
Person("Manish", 30),
Person("Kunal", 24)
)
val filteredResult = persons
.map { it.name }
.also { println(it) }
.filter { it.length > 5 }
println(filteredResult)

5. with

Similar to apply function, with is also used to change properties of an instance i.e. object configuration. Only difference is with is not an extension function. The last expression of with function returns a result. Simply as per docs

In the code, with can be read as “with this object, do the following.”

data class Person(val name: String, val age: Int, var job: String, var address: String)

fun coolFunction() {
val person = Person("Vinay", 29, "Developer", "Mumbai")
with(person) {
job = "Sr. Developer"
address = "Bangalore"
}
println(person)
}

Do use these functions in your code but be careful. Sometimes the code may look over engineered. So choose valid use cases to use these functions. This is very useful link which sort of explains Dos and Don’ts .


The Startup

Medium's largest active publication, followed by +708K people. Follow to join our community.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store