【发布时间】:2017-09-11 18:17:32
【问题描述】:
虽然问题提供的代码相当琐碎,但问题集中在类型安全的更一般方面:
让我们有一个像这样的 lambda 函数:
{it: (Any) -> Any -> it(it)}
它接受另一个 lambda 并以自身作为参数执行它。所以让我们做显而易见的事情并将其作为参数调用:
{it: (Any) -> Any -> it(it)}.apply { this.invoke(this) }
但这并不像我想的那样好用:我在编译时收到以下错误:
类型不匹配:推断类型为 ((Any) -> Any) -> Any but (Any) -> Any 是预期的
好的。所以让我们试试这个:
val lambda: (Any) -> Any = { Unit }
这个属性的实际值无关紧要,我对结果不感兴趣,只对编译器行为感兴趣。所以这是另一个属性:
val kappa: (Any) -> Any = lambda
好的,现在这实际上编译了。但这不是和以前一样吗?我将一个 (Any) -> Any 函数传递给一个属性(在另一种情况下它是一个参数),它需要一个 (Any) -> Any 函数。逻辑告诉我:是的,(Any) -> Any 是 Any 类型,因为一切都是。但是为什么这不适用于 lambda 调用呢?事实上,我可以将我的 lambda 显式转换为 (Any) -> Any 函数,这将导致未经检查的转换,但它会按预期编译和执行导致 StackOverflowError。
{it: (Any) -> Any -> it(it)}.apply { this.invoke(this as (Any) -> Any) }
区别在哪里?
【问题讨论】:
-
我认为您的第一个假设是错误的。在定义中:
{it: (Any) -> Any -> it(it)},所有的it都是同一个东西。 -
是的,为什么不呢?它是一个将任何内容作为输入的函数,它应该包括另一个(或相同)将任何内容作为输入的函数。
-
是的,你找到我了。
it的完全混淆使用完全成功地让我感到困惑。将(Any) -> Any -> Any转换为(Any) -> Any是未经检查的转换。您的第二个示例没有未经检查的演员表。 -
FWIW,
kappas mutator 的签名是set(f: (Any) -> Any)。 -
好的,虽然我明白为什么使用 mutator 是类型安全的,但我仍然不明白,为什么 ((Any) -> Any) ->Any 的强制转换未选中。根据我的理解,我应该能够将函数作为期望 Any 的参数传递,因为 Any 应该包含一个函数。