sat
sat

Reputation: 5709

What does <ClassName>.() mean in Kotlin?

Not sure what this means but I came across this syntax in the kotlin html codebase. What does SCRIPT.() mean?

https://github.com/Kotlin/kotlinx.html/blob/master/shared/src/main/kotlin/generated/gen-tag-unions.kt#L143

fun FlowOrPhrasingOrMetaDataContent.script(type : String? = null, src : String? = null, block : SCRIPT.() -> Unit = {}) : Unit = SCRIPT(attributesMapOf("type", type,"src", src), consumer).visit(block)

SCRIPT is a class - https://github.com/Kotlin/kotlinx.html/blob/master/shared/src/main/kotlin/generated/gen-tags-s.kt.

Or more generally, what does <ClassName>.() mean in Kotlin?

Upvotes: 19

Views: 4165

Answers (2)

Amit
Amit

Reputation: 667

What does .() mean in Kotlin?

They are called function literals with receiver.

The following is an example to try to explain the same:

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) }
)

These functional literals with receiver types are similar to extension functions.

Upvotes: 0

s1m0nw1
s1m0nw1

Reputation: 81859

Quick answer

block: SCRIPT.() -> Unit = {}

This represents a “function literal with receiver”. It’s a function parameter with a function type () -> Unit and SCRIPT as it’s receiver.

Function Literals/Lambda with Receiver

Kotlin supports the concept of “function literals with receivers”. It enables the access on visible methods and properties of a receiver of a lambda in its body without any specific qualifiers. This is very similar to extension functions in which it’s also possible to access visible members of the receiver object inside the extension.

A simple example, also one of the greatest functions in the Kotlin standard library, isapply:

public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }

As you can see, such a function literal with receiver is taken as the argument block here. This block is simply executed and the receiver (which is an instance of T) is returned. In action this looks as follows:

val foo: Bar = Bar().apply {
    color = RED
    text = "Foo"
}

We instantiate an object of Bar and call apply on it. The instance of Bar becomes the “receiver”. The block, passed as an argument in {}(lambda expression) does not need to use additional qualifiers to access and modify the shown visible properties color and text.

The concept of lambdas with receiver is also the most important feature for writing DSLs with Kotlin.

Upvotes: 29

Related Questions