是否可以从 lambda 的闭包中隐藏变量?

Is it possible to hide variables from lambda's closure?

我正在尝试在 Kotlin 中创建一个类型安全的 groovy 风格的构建器,就像它所描述的那样 here。 问题是嵌套 lambda 中 lambda 接收器的可见性。 这是一个简单的例子。

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

嵌套 lambda 的接收者是没有 'head' 方法的 Body。尽管如此,这段代码编译并打印成这样:

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

这是预料之中的,但是有什么方法可以让内头出现编译错误吗?

从 Kotlin 1.0 开始,这是不可能的。此功能有一个 open feature request

由于 introduction of the @DslMarker annotation.

,自 Kotlin 1.1 以来这是可能的

这是一个如何使用它的例子:

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

另请参阅上面链接的公告中的文档。