Можно ли скрыть переменные от закрытия лямбды?


Я пытаюсь создать типобезопасный конструктор в стиле groovy в Котлине, как это описано здесь. Проблема заключается в видимости лямбда-приемников во вложенных лямбдах. Вот простой пример.

html {
    head(id = "head1")
    body() {
        head(id = "head2")
    }
}

Получателем вложенной лямбды является тело, которое не имеет метода "head". Тем не менее этот код компилируется и печатается в этом:

<html>
    <head id="head1"></head>
    <head id="head2"></head>
    <body></body>
</html>

Это ожидается, но есть ли способ получить ошибку компиляции на внутренней голове?

2 5

2 ответа:

По состоянию на Kotlin 1.0 это невозможно. Существуетоткрытый запрос функции для этой функции.

Это возможно начиная с Kotlin 1.1, благодаря введению аннотации @DslMarker .

Вот пример того, как его можно использовать:

@DslMarker
annotation class MyHtmlDsl

@MyHtmlDsl
class HeadBuilder

@MyHtmlDsl
class BodyBuilder

@MyHtmlDsl
class HtmlBuilder {
    fun head(setup: HeadBuilder.() -> Unit) {}
    fun body(setup: BodyBuilder.() -> Unit) {}
}

fun html(setup: HtmlBuilder.() -> Unit) {}

fun main(args: Array<String>) {
    html {
        head {}
        body {
            head { } // fun head(...) can't be called in this context by implicit receiver
        }
    }
}

См. также документацию по объявлению, приведенному выше.