with()
with()
works nearly identically to run()
. Both cause an object to become the this
inside the lambda expression, and both return the results of the last statement in that lambda expression.
The difference lies in where the object comes from:
- With
run()
, you callrun()
on the object - With
with()
, you pass the object as a parameter:
data class IntPropertyBag(private val pieces: MutableMap<String, Int> = mutableMapOf()) {
fun set(key: String, value: Int) {
pieces[key] = value
}
}
fun main() {
val ultimateStuff = with(IntPropertyBag()) {
set("ID", 330258648)
set("YEAR", 1979)
set("HOW_MANY_ROADS_MUST_A_MAN_WALK_DOWN", 42)
toString()
}
println(ultimateStuff)
}
However, this introduces a subtle change: run()
is more flexible with nullable types than is with()
. With run()
, you can use ?.
to conditionally call run()
if the object (the “receiver”) is not null
:
var thing: String? = "foo"
val nonNullResult = thing?.run { this.isNotBlank() }
println(nonNullResult)
thing = null
val nullResult = thing?.run { this.isNotBlank() }
println(nullResult)
This prints:
true
null
In both cases, we are using thing?.run { this.isNotBlank() }
, where isNotBlank()
returns true
if the string has one or more non-whitespace characters. In the case where thing
is "foo"
, run()
is called, because thing
is not null
. Where thing
is null
, though, the ?.
skips the run()
call, and so nullResult
also winds up as null
. We do not need ?.
on the isNotBlank()
call, because the Kotlin compiler knows that the ?.run()
cannot wind up with a null
value.
With with()
, though, the safe-call operator (?.
) is not an option — we pass the possibly-null value as the parameter. Our lambda expression would need to be able to deal with the possibly-null value.
In summary, with()
:
- Is passed some object
- Takes whatever you call it on and makes it be the “current” object —
this
— in the scope of the lambda expression - Returns whatever the last statement of the lambda expression evaluates to
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.