6

I'm looking at this Kotlin object declaration:

object A : B({
    variableName1 = "text1"
    variableName2 = "text2"

    params {
        param("Foo", "Bar")
    }
})

And I cannot figure out what the argument to class B's constructor is.

I have purposefully abstracted away information in this example but class B is actually

jetbrains.buildServer.configs.kotlin.v10.BuildType

And I cannot find the documentation for the type. I have found something that was close but it's a definition for an interface and thus doesn't have a constructor.

To summarise, what is this the following construct in Kotlin?

{
    variableName1 = "text1"
    variableName2 = "text2"

    params {
        param("Foo", "Bar")
    }
}
s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
ZoSal
  • 561
  • 4
  • 21
  • 3
    https://confluence.jetbrains.com/display/TCD10/Kotlin+DSL – Yoav Sternberg Oct 12 '17 at 09:13
  • 1
    @YoavSternberg This is what I was looking at and got puzzled with. I may have just missed the phrase that said the argument was a function literal with receiver. – ZoSal Oct 12 '17 at 09:18

3 Answers3

10

This construct is called "Lambda with Receiver", aka "Function Literal with Receiver", which you'll find used in Kotlin DSL implementations extensively. For an example, have a look at the HTML builder DSL.

I described the whole concept in detail in this thread.

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
0

An example to try to explain function literal / lambda with receiver type:

data class Person(val name: String)

fun getPrefixSafely(
    prefixLength: Int,
    person: Person?,
    getPrefix: Person.(Int) -> String): String
{
    if (person?.name?.length ?: 0 < prefixLength) return ""
    return person?.getPrefix(prefixLength).orEmpty()
}

// Here is how getPrefixSafely can be called
getPrefixSafely(
    prefixLength = 2,
    person = Person("name"),
    getPrefix = { x -> this.name.take(x) }
)

PS: These lambdas with receiver types are similar to extension functions IMO.

Amit Dash
  • 584
  • 8
  • 21
0

Lambda with receiver is a powerful concept in Kotlin that can greatly simplify the process of creating and configuring RecyclerView adapters in Android development. By leveraging lambda with receiver, you can write concise and expressive code, create fluent APIs, and simplify common tasks. Let's see how lambda with receiver can simplify RecyclerView adapters:

In the example code provided, the MyAdapter class extends RecyclerView.Adapter and takes a List and an onItemClick lambda as parameters:

class MyAdapter(private val items: List<String>, private val onItemClick: (String) -> Unit) :
    RecyclerView.Adapter<MyAdapter.ViewHolder>()

Inside the ViewHolder class, the bind function is defined to bind the data and handle item clicks:

inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    fun bind(item: String) {
        itemView.setOnClickListener { onItemClick(item) }
        itemView.textView.text = item
    }
}

To simplify the process of creating and configuring the adapter, you can use lambda with receiver to pass the onItemClick lambda directly when creating the adapter:

val adapter = MyAdapter(items) { item ->
    // Handle item click
    showToast("Clicked: $item")
}

By utilizing lambda with receiver, you provide a clean and concise way to handle item clicks. The onItemClick lambda allows you to define the behavior when an item is clicked, in this case, displaying a toast message.

This approach enhances the readability and maintainability of your code, as it eliminates the need for creating separate interfaces or anonymous inner classes to handle item clicks. Additionally, it provides a more expressive and fluent API for working with RecyclerView adapters.

By embracing the power of lambda with receiver, you can simplify your RecyclerView adapters and write cleaner, more expressive code that is easier to maintain.