Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin equivalent of Swift's defer keyword

Is there anything similar in Kotlin that provides same ability as the Swift keyword 'defer' ?

What the defer key word does is, it ensure that the code inside a defer block get executed before returning from a function.

Below is an example imagining that defer keyword existed in Kotlin.

    class MyClass {

        var timeStamp = 0L

        fun isEdible(fruit: Fruit): Boolean {
          defer { 
           timeStamp = System.currentTimeMillis()
          }
          if (fruit.isExpired) {
             return false
          }
          if (fruit.isRipe) {
            return true
          }
          return false
        }
     }

In the case above, regardless of at what point the function returns, the block inside defer will get executed and timestamp's value will get updated, just before the function ends.

I know Java there is the finally {} keyword used along with try{} catch{}, but it's is not exactly what defer offers.

like image 472
rgv Avatar asked Jan 27 '23 18:01

rgv


2 Answers

There's no such keyword in Kotlin, but you can make a construct yourself that will work quite similarly. Something like this (note that this does not handle exceptions in the deferred blocks):

class Deferrable {
    private val actions: MutableList<() -> Unit> = mutableListOf()

    fun defer(f: () -> Unit) {
        actions.add(f)
    }

    fun execute() {
        actions.forEach { it() }
    }
}

fun <T> defer(f: (Deferrable) -> T): T {
    val deferrable = Deferrable()
    try {
        return f(deferrable)
    } finally {
        deferrable.execute()
    }
}

Then you can use it like this:

class MyClass {

    var timeStamp = 0L

    fun isEdible(fruit: Fruit): Boolean = defer { d ->
      d.defer { 
       timeStamp = System.currentTimeMillis()
      }
      if (fruit.isExpired) {
         return false
      }
      if (fruit.isRipe) {
        return true
      }
      return false
    }
}
like image 114
marstran Avatar answered Jan 31 '23 11:01

marstran


The closest equivalent is try/finally. catch is not necessary if there's no exceptions thrown.

try {
    println("do something")
    // ... the rest of your method body here
}
finally {
    println("Don't forget about me!");
}

In Swift, defer is usually used to ensure you don't forget to clean up some kind of resource or another (file handle, database connection, shared memory map, etc.). For this purpose, Kotlin use with, which takes a closure, to which the resource is passed as an argument. The resource is valid for the lifetime of the closure, and is automatically closed at the end.

FileWriter("test.txt")
  .use { it.write("something") }
// File is closed by now
like image 27
Alexander Avatar answered Jan 31 '23 11:01

Alexander