Kotlin Difference of let, also, apply, run, with

July 25, 2018
when to use what
Function Argument/Receiver Lambda Result Remark
let it yes
also it no/self
run this yes
apply this no/self
with this yes not extension

Discussion on run vs with

let

  • provide argument it
  • return a result (can be Any)
val name: String? = "hello"
val result = name?.let {
    it.toUpperCase()
}
assertEquals(result, "HELLO")
val result = name?.let {
    it.toUpperCase()
    100
}
assertEquals(result, 100)
val result = name?.let {

}
assertEquals(result, Unit)

also

  • provide argument it
  • doesn’t return a result / same object
val name: String? = "hello"
val result = name?.also {
    it.toUpperCase()
}
assertEquals(result, "hello")
val result = name?.also {
    it.toUpperCase()
    100
}
assertEquals(result, "hello")
val result = name?.also {

}
assertEquals(result, "hello")

run

  • change argument this
  • return a result (can be Any)
val name: String? = "hello"
val result = name?.run {
    toUpperCase()
}
assertEquals(result, "HELLO")
val result = name?.run {
    toUpperCase()
    100
}
assertEquals(result, 100)
val result = name?.run {

}
assertEquals(result, Unit)

apply

  • change argument this
  • doesn’t return a result / same object
val name: String? = "hello"
val result = name?.apply {
    toUpperCase()
}
assertEquals(result, "hello")
val result = name?.apply {
    toUpperCase()
    100
}
assertEquals(result, "hello")
val result = name?.apply {

}
assertEquals(result, "hello")

with

  • change argument this
  • return a result (can be Any)
  • not extension function
  • not suited for null checking or call chaining
val result = with(name) {
    this?.toUpperCase()
}
assertEquals(result, "HELLO")
val result = with(name) {
    this?.toUpperCase()
    100
}
assertEquals(result, 100)
val result = with(name) {

}
assertEquals(result, Unit)
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.