44

Do with and run have the same functionality with only different syntax, or is there any major differences between with and run?

Which is the proper way?

adapter.run {
    notifyDataSetChanged()
    if (activityDetails.isEmpty())
        emptyText.visibility = View.VISIBLE
    else 
       emptyText.visibility = View.GONE
}


with(adapter){
   notifyDataSetChanged()
   if (activityDetails.isEmpty())
       emptyText.visibility = View.VISIBLE
   else 
       emptyText.visibility = View.GONE
}
hotkey
  • 140,743
  • 39
  • 371
  • 326
Sai
  • 15,188
  • 20
  • 81
  • 121

2 Answers2

49

They have only syntactic difference, run is an extension function while with is not. Here are the definitions (in kotlin-sdlib:1.0.3):

public inline fun <T, R> T.run(block: T.() -> R): R = block() // equivalent to this.block()

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

Since run is an extension function, it has one more implicit argument of type T, so the argument types are the same. The bodies of the functions are also effectively the same.

Their performance should also be equivalent since both are inline functions: the resulting bytecode should only contain the inlined block body.


The differences in the functions usage are all caused by the fact that run is an extension.

First, run is suitable for calls chaining:

foo.run { bar }.run { baz }

Second, and more important, if a declared variable type has run function with the same signature, it will be called instead of the extension. And run can be shadowed by another extension. This is how extensions are resolved. Example:

class MyClass {
     fun <R> run(blockIgnored: MyClass.() -> R): Nothing = throw RuntimeException()
}

"abcdefg".run { println("x") } // prints "x"
MyClass().run { println("x") } // throws RuntimeException
(MyClass() as Any).run { println("x") } // prints "x"
hotkey
  • 140,743
  • 39
  • 371
  • 326
  • 1
    So i can user either. Dose both have any influence on performance of the application ? – Sai Jul 21 '16 at 11:01
  • 2
    @SaiKiran, yes, they are completely interchangeable, and their performance should be the same since they are both `inline` functions. – hotkey Jul 21 '16 at 11:02
  • "We recommend with for calling functions on the context object without providing the lambda result." https://kotlinlang.org/docs/reference/scope-functions.html#with – methodsignature Jul 06 '20 at 19:22
19

In normal case, they are pretty similar, but for a nullable variable, it's better to use T.run()

E.g. if webview.settings is nullable, below would show the distinct

with(webview.settings) {
    this?.javaScriptEnabled = true
    this?.databaseEnabled = true
}

// similarly
webview.settings?.run {
    javaScriptEnabled = true
    databaseEnabled = true
}
Elye
  • 53,639
  • 54
  • 212
  • 474
  • I guess it is even better to use "apply" in this scenario – K.Os May 23 '20 at 16:41
  • Ya, but this is to answer the question of `with` vs `run`. As of when to use which, perhaps this article would help. https://medium.com/@elye.project/mastering-kotlin-standard-functions-run-with-let-also-and-apply-9cd334b0ef84 – Elye May 24 '20 at 02:22
  • 1
    the return from the scope function is not used. would you please explain why is it better using "apply" in this case? – Sean Sep 14 '20 at 20:29
  • @sean I would not use apply in this case because as you said nothing is being returned. – dumamilk Jul 07 '21 at 19:42