43

It seems that the last line of a lambda always returns that value even if you omit the return statement. Is this correct? Is it documented anywhere?

fun main(args: Array<String>) {
    val nums = arrayOf(1, 2, 3)
    val numsPlusOne = nums.map { it -> 
        val r = it + 1
        r
    }
    // numsPlusOne = [2, 3, 4]
}
Will
  • 3,770
  • 3
  • 21
  • 19
  • 6
    Just a helpful hint, you can shorten that to `val numsPlusOne = nums.map { it + 1 }` (because `it` is implied if not specified, and if `it + 1` is the last line, its result will be returned as @hotkey explained) – Ruckus T-Boom Jan 12 '17 at 20:52

1 Answers1

59

Yes, this is correct, if the last statement of a lambda is an expression, it is considered its return value.

Here's what the reference says (thanks @KirillRakhman):

We can explicitly return a value from the lambda using the qualified return syntax. Otherwise, the value of the last expression is implictly returned. Therefore, the two following snippets are equivalent:

ints.filter {
    val shouldFilter = it > 0 
    shouldFilter
}

ints.filter {
    val shouldFilter = it > 0 
    return@filter shouldFilter
}

The last statement semantics is also true for if (that's why there's no ternary operator), when and try-catch blocks, and these statements are expressions themselves:

val foo = if (bar) { 
    doSomething()
    baz 
} else { 
    doSomethingElse()
    qux 
}

See also: examples for when and try-catch.

So, lambdas are consistent with the language constructs in this respect.


If you want to make an explicit return statement in a lambda, use the return@label syntax (also, another answer with examples). Non-labeled return, on contrary, works with the nearest fun (ignoring lambdas) and thus can only occur in those lambdas which are inlined.

There was a language proposal to add special syntax for emitting a value from a code block, but it was rejected.

Community
  • 1
  • 1
hotkey
  • 140,743
  • 39
  • 371
  • 326
  • "if the last statement of a lambda is an expression" - I can't find a definitive source for definitions, but I think it's incorrect to call the "expression" a "statement". The Kotlin docs only say "the value of the last expression is implicitly returned". My understanding is that statements typically don't produce values and that an `expression` is not a type of `statement` – mowwwalker Oct 05 '20 at 17:28
  • 1
    @mowwwalker Well, while this is arguable, in [the Kotlin grammar](https://kotlinlang.org/docs/reference/grammar.html#statements), one kind of a statement is an expression, which may be a dangling unused value or a function call whose return value is ignored. – hotkey Oct 05 '20 at 18:39
  • Ah awesome that settles that then :) – mowwwalker Oct 05 '20 at 19:43