Kotlin Scope Functions

Kotlin Scope Functions

Scope functions is one of the Kotlin feature I really like. When using such a function on an object, you are executing a block of code within the context of that object. You won’t find a similar feature in Java. There are five scope functions available in Kotlin: let, apply, run, with and also. In fact all of them is doing the same thing – execute a block of code on an object. However, there are some differences and we will discuss them on the simple example of code.

Example

The source code repository used for this article is available on my GitHub in repository sample-kotlin-playground. It is available here: https://github.com/piomin/sample-kotlin-playground.git.

Apply scope function

Apply refer to the context object as a lambda receiver – by keyword this. It is the same as “you would be inside” the class of that object. You can even omit the keyword this. As a results it just returns the context object. All these features makes it ideal for changing value of object fields. Let’s take a look on the following example of code. Then we will try to implement the same functionality using other scope function.

@Test fun testApplyFunction() {
  val p: Person = Person("John", "Smith", 1)
    .apply {
      age = 20
      localization = "London"
    }
  Assert.assertEquals(20, p.age)
  Assert.assertEquals("London", p.localization)
}

Let

Let is able to access the context object as a lambda argument. If the argument name is not specified, the object is accessed by the implicit default name it. It is returning the lambda result. What means that if we want to do the same thing with person object as in the previous sample we need to return exactly that object.

@Test fun testLetFunction() {
  val p: Person = Person("John", "Smith", 1)
    .let {
      it.age = 20
      it.localization = "London"
      it
    }
  Assert.assertEquals(20, p.age)
  Assert.assertEquals("London", p.localization)
}

Run scope function

Run the same as apply function refers to the context object as a lambda receiver. But unlike apply it returns the lambda result instead of the context object. The test is very similar to the testApplyFunction – the only difference is that we have to return object using this keyword.

@Test fun testRunFunction() {
  val p: Person = Person("John", "Smith", 1)
    .run {
      age = 20
      localization = "London"
      this
    }
  Assert.assertEquals(20, p.age)
  Assert.assertEquals("London", p.localization)
}

Also scope function

We can use also function to do some additional work after previous changes. Let’s implement our test with apply in slightly different way. Function also returns the context object and takes the context object as a lambda argument.

@Test fun testAlsoFunction() {
  val p: Person = Person("John", "Smith", 1)
    .apply {
      age = 20
      localization = "London"
    }
    .also {
      Assert.assertEquals(20, it.age)
      Assert.assertEquals("London", it.localization)
    }
}

TakeIf scope function

TakeIf is not a scope function. It is in addition provided by the Kotlin standard library together with takeUnless. While takeIf returns this object if it matches the predicate, takeUnless returns the object if it doesn’t match the predicate and null if it does. Let’s take a look on the simple test that illustrates usage of this function.

@Test fun testTakeIfFunction() {
  var p: Person? = Person("John", "Smith", 1).takeIf { it.id > 1 }
  Assert.assertNull(p)
  p = Person("John", "Smith", 1).takeIf { it.id == 1 }
  Assert.assertNotNull(p)
}

4 COMMENTS

comments user
waheed388

Hi Piotr,

Thank for such an informative lesson, I really liked your teaching style. Explaining all the concepts with real code-based examples. It is a good approach.

    comments user
    Piotr Mińkowski

    Thanks 🙂

comments user
itsmepriyavika

Hi Piotr
Very insightful content.

I have written a well researched content on Kotlin and its benefits.
https://appsierra.com/what-is-kotlin-the-alternative-of-java-explained/

    comments user
    Piotr Mińkowski

    Hi. Thanks 🙂

Leave a Reply