kotlin

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?


Solution

  • 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.