innov8
innov8

Reputation: 2219

within a kotlin lambda, how does a string accept a lambda?

In gradle-kotlin-dsl... this is valid code

tasks {
   "build" {
      // inner lambda code here

How can it work that a string can accept a lambda parameter, or else how is this syntax working? The string "build" seems to one of a list of strings that substitute for function calls? Something in the applicable class definition must set up this behaviour, but I cannot think how that is done.

The way this works could be a technique that has other uses, but to evaluate that, it is necessary to know how it works!

Upvotes: 0

Views: 230

Answers (1)

zsmb13
zsmb13

Reputation: 89578

This is a combination of a couple of Kotlin language features which are often used for creating DSLs, specifically:

  • the invoke operator, which lets you define the () function call operator for a type, with an arbitrary parameter list (docs)
  • being able to pass a last lambda parameter to a function outside the parantheses you usually need for the parameter list (docs)
  • extensions, letting you add new methods to existing types, even if you don't own them (docs)

To achieve the syntax you've asked about specifically, you could write a method like this:

operator fun String.invoke(block: () -> Unit) {
    // Do whatever you'd like with the String and the lambda
    // you received as a parameter
}

The lambda you're taking as the parameter could also be an extension on any type you'd like (perhaps String itself, but depends on your use case), could take parameters, or be expected to return a value instead of just Unit.

The point is that inside this extension, you'll have access to the String it was called on as this and you'll have the lambda that was passed to it.


For further reference, here's a multi-part article that shows off some DSL building techniques.

Upvotes: 2

Related Questions