What does "with" mean in Kotlin?

The definition of with:

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

Actually it's implementation is straight forward: The block is executed on receiver, which works for any type:

receiver.block() //that's the body of `with`

The great thing to mention here, is the parameter type T.() -> R: It's called function literal with receiver. It's actually a lambda that can access the receiver's members without any additional qualifiers.

In your example the context of with receiver app is accessed in that way.

Besides stdlib functions like with or apply, this functionality is what makes Kotlin great for writing Domain Specific Languages as it allows the creation of scopes within which you have access on certain functionalities.


with is used to access an object's members and methods without having to refer to the object once per access. It is (mostly) for abbreviating your code. It is frequently used when constructing an object:

// Verbose way, 204 characters:
var thing = Thingummy()
thing.component1 = something()
thing.component2 = somethingElse()
thing.component3 = constantValue
thing.component4 = foo()
thing.component5 = bar()
parent.children.add(thing)
thing.refcount = 1

// Terse way, 182 characters:
var thing = Thingummy()
with(thing) {
  component1 = something()
  component2 = somethingElse()
  component3 = constantValue
  component4 = foo()
  component5 = bar()
  parent.children.add(this)
  refcount = 1
}

The documentation says:

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

Calls the specified function block with the given receiver as its receiver and returns its result.

The way I think of it is that it is calling a function (the block) where this in the scope of the block is the receiver. Whatever the block returns is the return type.

Essentially calling a method where you provide the implicit this and can return any result from it.

Here is an example to demonstrate:

val rec = "hello"
val returnedValue: Int = with(rec) {
  println("$this is ${length}")
  lastIndexOf("l")
}

The rec in this case is the receiver of the function call - the this in the scope of the block. The $length and lastIndexOf are both called on the receiver.

The return value can be seen to be an Int because that is the last method call in the body - that is the generic type parameter R of the signature.

Tags:

Kotlin