Here is step by step explaination:
1. Creation of function, receiver type lambda.
fun html(init: HTML.() -> Unit): HTML {
here function html accept a parameter init
of type HTML.() -> Unit
i.e. it indicated that it is a receiver of HTML and can only be called with help of a real HTML object. And : HTML
indicates that the function obviously returns HTML object.
2. call of init at html
html.init()
Here init() function is called as a receiver of HTML by a real HTML object.
Alright enough of formal talking, Here is what a receiver is:
So if you remember extension function defined as fun A.myFun(...): ReturnType {}
, in that case you get a variable this
which act as an instance of type A it was called on.
Similarly receiver lambda gives you a this
variable inside that,
In a particular example:
class A {
fun thisCanBeCalledByAInstance() {
println("I've got called")
}
}
fun main() {
val receiver: A.() -> Unit = { // this: A
thisCanBeCalledByAInstance() // prints: I've got called
// or traditional way this.thisCanBeCalledByAInstance()
}
val a: A = A()
a.receiver()
}
Here you were able to call the method(function) from the instance of A
even if it was lambda because it was a receiver.
PS: For simple langauge you can think html.init() as init(html) but html is not a parameter but instead works as this
vaiable inside the lambda
This is why you were able to call body()
on that lambda, because implicitly you were calling this.body()
and this
has came from html.init()
's html object.