The Kotlin standard library contains several functions whose sole purpose is to execute a block of code within the context of an object. When you call such a function on an object with a lambda expression provided, it forms a temporary scope. In this scope, you can access the object without its name. Such functions are called scope functions. There are five of them: let, run, with, apply, and also.
Reusable sequences of code are often times extracted to another function to achieve reusability. However, this approach could easily end you up with a class littered with small functions with no clear relationship between each other. Grouping these functions could also net you a lot of boilerplate code. Wouldn’t it be nice to extract these functions and scope them to the function that requires them to make relationships clear without any boilerplate code?
Basically, these functions do the same: execute a block of code on an object. What’s different is how this object becomes available inside the block and what is the result of the whole expression. Kotlin “scope functions” are functions that allow for changing the scope, or the range, of a variable. There are five such functions included in the Kotlin standard library: apply, run, with, let, and also.
In Kotlin, functions are as important as integers or strings. Functions can exist on the same level as classes, may be assigned to variables and can also be passed to/returned from other functions. Kotlin makes functions “first-class citizens” of the language, which Wikipedia describes as follows:
A first-class citizen […] is an entity which supports all the operations generally available to other entities. These operations typically include being passed as an argument, returned from a function, modified, and assigned to a variable.
As already said, functions are as powerful and significant as any other type, e.g. Int. In addition to that, functions may appear as “higher-order functions”, which in turn is described as the following on Wikipedia:
In mathematics and computer science, a higher-order function (also functional, functional form or functor) is a function that does at least one of the following:
- takes one or more functions as arguments (i.e., procedural parameters),
- returns a function as its result.
The boldly printed bullet point is the more important one for the present article since scope functions also act as higher-order functions that take other functions as their argument. Before we dive into this further, let’s observe a simple example of higher-order functions.