DEV Community

Vijay Vimalananda Guru
Vijay Vimalananda Guru

Posted on

Understanding Kotlin's Scope Functions

What are Scope Functions?

Scope Functions are a part of Kotlin standard library. It executes a block of code within that context of an object. Using these functions on an object with lambda expression, it provides a temporary scope for that object which is either accessible by it(default) or this, depending on function type. With this we can access those objects without their names. Thereby it makes the code simple, clean and easily readable. There are 5 different types of scope functions in Kotlin: let, with, run, also & apply.

When to choose what?
To choose the right function for your requirement, please check the below table.

Image description

let:
let is primarily used along with a safe call operator (?.) to prevent NullPointerException. It will execute the block of code only if the object is not null.

fun main (){
    val name: String? = null
    println(name!!.length)
}
Enter fullscreen mode Exit fullscreen mode

Output:
Exception in thread "main" java.lang.NullPointerException

Using let function:

fun main (){
    val name: String? = null
    name?.let{
        println(name!!.length) //statement will not execute 
                               //as name is null
    }
}
Enter fullscreen mode Exit fullscreen mode

with:
with is used for calling functions on context objects without providing the lambda result. It is used to access members and methods of an object without having refer to it.

Using with function:

class Person {
    var name: String = ""
    var age: Int = 0
}

fun main() {
    val person = Person()
    with(person) {
        name = "Vijay"
        age = 30
        println("Name: $name, Age: $age")
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:
Name: Vijay, Age: 30

Inside the with block, you can directly access the properties (name and age) of the person object without explicitly referencing person. This can lead to more concise and readable code, especially when performing multiple operations on the same object.

run:
run is a combination of 'let' and 'with' functions. Imagine a null value is assigned to an object and we want to prevent it from NullPointerException. In this case, we can use run function with that object.

Using run function:

class Person {
    var name: String = ""
    var age: Int = 0
}

fun main() {
    val person = Person()
    val result = person.run {
        name = "Vijay"
        age = 30
        "Name: $name, Age: $age"
    }

    println(result)
}
Enter fullscreen mode Exit fullscreen mode

Output:
Name: Vijay, Age: 30

The run function also returns the result of the last expression inside its block, which is a string containing the name and age of the person.

also:
also is used where we want to perform additional operations when we have initialized the object member.

Using also function:

class Person {
    var name: String = ""
    var age: Int = 0
}

fun main() {
    val person = Person()
    val result = person.also {
        it.name = "Vijay"
        it.age = 30
    }.let {
        "Name: ${it.name}, Age: ${it.age}"
    }
    println(result)
}
Enter fullscreen mode Exit fullscreen mode

Output:
Name: Vijay, Age: 30

The let function is called on the returned object (person). It takes a lambda with the parameter it, which refers to the object returned by also. Inside the let block, a string is created using the properties of the object returned by also. The result is assigned to the result variable.

apply:
apply is mostly used for initializing the objects. It is also used to configure specific attributes of that object.

Using apply function:

class Person {
    var name: String = ""
    var age: Int = 0
}

fun main() {
    val person = Person()
    val result = person.apply {
        name = "John"
        age = 30
    }.let {
        "Name: ${it.name}, Age: ${it.age}"
    }
    println(result)
}

Enter fullscreen mode Exit fullscreen mode

Output:
Name: Vijay, Age: 30

The difference between apply _and _also is, apply is more focused on modifying and initializing objects and returning them, while also is more about performing side effects or additional actions without altering the object and then returning it.

Top comments (0)