avatarSatya Pavan Kantamani

Summary

This context provides an in-depth explanation of Kotlin scope functions, including their purpose, different types, and use cases.

Abstract

The context begins by introducing Kotlin scope functions, which are functions that execute a block of code within the context of an object. It then explains the concept of the context object and how it can be referred to as either 'it' or 'this' within the lambda expression. The context goes on to describe the five different scope functions available in Kotlin: let, run, with, apply, and also. Each function is explained in detail, including its syntax, the way it refers to the context object, and its return value. The context also provides examples of how to use each function and discusses their use cases. Finally, the context summarizes the key points and provides references for further reading.

Bullet points

  • Kotlin scope functions execute a block of code within the context of an object.
  • The context object can be referred to as either 'it' or 'this' within the lambda expression.
  • There are five different scope functions available in Kotlin: let, run, with, apply, and also.
  • Each function has its own syntax, way of referring to the context object, and return value.
  • The context provides examples of how to use each function and discusses their use cases.
  • The context summarizes the key points and provides references for further reading.

Kotlin Advanced Programming (Part 3)

Learn about Kotlin scope functions

If you’re new to Kotlin please check out my previous posts:

In this article we’re going to check check out scope functions in Kotlin and how to use them.

What are Scope Functions?

In Kotlin functions are of great importance. Scope functions are functions that execute a block of code within the context of an object. When we call such functions on an object with a lambda expression, it forms a temporary scope where we can perform our operations. In that scope, the context of the object is generally referred to as it (or any custom name) or this based on the scope function we are using.

Let’s take a simple example of the run function:

Here, inside sample(), a value is defined as 1 but inside run scope it has been redefined — the modified value is valid until the end of the scope. Scope functions are very useful and we can find many ways to use them.

Different Scope Functions

There are five different scope functions available in Kotlin. These are: let, run, with, apply, and also. All five functions do the same thing: execute a block of code on an object. They differ in two main ways:

  • The way to refer to the context object
  • The return value.

Before we dive in, let’s explore the context object. We generally refer to the context object inside a lambda expression using a short name. Each scope function uses either one of the two ways to access the context object as a lambda receiver (this) or as a lambda argument (it). Let’s check each of them.

this — as the receiver

In the scope functions apply, run, and with the context object is referred by keyword this . They have the context object as a lambda receiver. In this case, we can omit this while accessing the members of the context object, making the code shorter and clean.

If we want to create a Person object we do it like this:

Using this with apply scope:

All the above methods are the same — they create the same Person object with the same values.

“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 members: call its functions or assign properties”

Kotlin documentation

it — as the argument

In the scope functions letand also the context object is referred by keyword it . They have the context object as a lambda argument. However, we have an option to specify the argument name here, if it’s not specified, the object is accessed by the implicit default name it . When we don’t have the object available implicitly, like this, we need to specify it pre-appended to them when calling the object functions or properties.

The return value

The scope functions differ by the result they return:

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

Which scope function is used can be decided based on what we do next to the scope function.

Next, let’s take a look at each of the scope functions

let

inline fun <T, R> T.let(block: (T) -> R): R

One of the most widely used scope functions during development for null checks mainly. The context object is available as an argument (it). The return value is the lambda result. NullPointerException is common in most programming languages.let is mostly used for executing code block only with 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.

It’s basically used for null checks with it as argument and for transformation takes one type of input and returns another type as a result.

run

inline fun <T, R> T.run(block: T.() -> R): R

The context object is available as a receiver (this). The return value is the lambda result. run can basically serve the same use cases however the only difference is the context object is available as this.

It is useful when our lambda contains both the object initialization and the computation of the return value.

apply

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

The context object is available as a receiver (this). The return value is the object itself.apply don’t return a value and mainly operate on the members of the receiver object.

Here the apply access the properties of City name and overrides its value. It’s similar to let — the only difference is that apply does not accept a return statement and always returns the same receiver object that it is referring to.

also

inline fun  T.also(block: (T) -> Unit): T

The context object is available as an argument (it). The return value is the object itself. It is very similar to apply — the only difference here is the way of referring to the context object. In apply we can provide a custom name instead, increasing readability in cases of let.

It can be used for the initialization of objects, improving the readability of code.

with

inline fun <T, R> with(receiver: T, block: T.() -> R): R

The context object is passed as an argument, but inside the lambda, it’s available as a receiver (this). The return value is the lambda result. It is similar to let and run in terms of the transformation of the receiver object to return type.

It’s used for better readability and is recommend for calling functions on the context object without providing the lambda result.

Summary

By now you should have a basic idea regarding the usage of scope functions in Kotlin. Check out my posts on Kotlin

References

Please give me your suggestions and comments!

Thanks for reading.

Android
Android App Development
Programming
Kotlin
Mobile
Recommended from ReadMedium