26

Passing a lambda to the last parameter

In Kotlin, there is a convention that if the last parameter of a function accepts a function, a lambda expression that is passed as the corresponding argument can be placed outside the parentheses:

val product = items.fold(1) { acc, e -> acc * e }

What is the purpose of this syntax?

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
vkelman
  • 1,501
  • 1
  • 15
  • 25
  • Hint: Have you looked at the function definition of `fold` or understand what it does? – OneCricketeer Feb 01 '19 at 21:49
  • 4
    @cricket_007 I don't think this question has anything to do with how the code works but rather the motivation for the syntax. vkelman, take a look at https://kotlinlang.org/docs/reference/type-safe-builders.html for some Kotlin code that makes extensive use of the ability to place the lambda outside of the parentheses to create a (in my opinion) very nice dsl. – SpencerPark Feb 01 '19 at 21:53
  • @SpencerPark While, yes, the blocks also work for DSL's, I am not sure that is what the question is about. With regards to `fold()` explicitly, the second argument is a function `(acc: R, nextElement: T) -> R` - https://kotlinlang.org/docs/reference/lambdas.html – OneCricketeer Feb 01 '19 at 21:57
  • 4
    @cricket_007 The example was taken word for word from the referenced documentation but the question is "What is the purpose of this syntax?". It looks like a question about language design but we will have to let vkelman clear that up. – SpencerPark Feb 01 '19 at 22:04
  • Well, the "purpose" is that it matches the method API. It's not the only way to write it, though. It could also be written as `items.fold(1, { ... })`, as shown in that last link – OneCricketeer Feb 01 '19 at 22:06
  • 7
    Well, I explicitly asked what is the purpose of this (confusing to me) syntax. I didn't ask what fold is doing. The answer I got - it allows for DSL. In my opinion, often those syntactic sugar things intended to prettify a language actually make code harder to understand. – vkelman Mar 19 '19 at 18:42

1 Answers1

25

This syntax gives Kotlin great DSL capabilities, it makes functions look like language constructions. For example:

with(car) {
   startUp()
   goToDestination()
}

Here with looks like it is language construction, whereas it is a simple function, receiving lambda as the last parameter.

And this leads to such elegant things like Kotlin HTML DSL

Max Farsikov
  • 2,451
  • 19
  • 25
  • 1
    How is a Domain Specific Language useful in kotlin? Why not just use the domain specific language instead if you're writing for a specific domain? – SMBiggs Jun 04 '22 at 05:04
  • @SMBiggs Most DSLs are implemented in traditional languages because it's generally not worthwhile to create an entire language just for a DSL. Some languages are more suited to DSLs than others, for example Groovy (the standard Gradle DSL is implemented in Groovy, although more recently you can also use Kotlin, and popular CI DSL such as Jenkins Job DSL is implemented in Groovy). There are also DSLs in Java such as Mockito for testing, although Java as a language is perhaps less suited to DSLs. – Adam Burley Nov 22 '22 at 12:05