Kotlin任何与lambdas

虽然提供这个问题的代码是相当微不足道的,但问题集中在类型安全的更一般的方面:

让我们有这样一个lambda函数:

{it: (Any) -> Any -> it(it)} 

它需要另一个lambda并将其自身作为参数执行。 所以让我们做一些明显的事情,并将其作为参数调用:

 {it: (Any) -> Any -> it(it)}.apply { this.invoke(this) } 

但是,这并不如我想的那样工作:在编译时出现以下错误:

类型不匹配:推断的类型是((任何) – >任何) – >任何,但(任何) – >任何预期

好。 所以我们来试试这个:

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

区别在哪里?

好的,正如我在评论中所说的那样,在这个问题提出的方式中,有很多不相干的混乱。 我们开始清理一下:

 val fn1 = {x1: (Any) -> Any -> x1(x1)} 

fn1的类型是((Any) -> Any) -> Anyx1的类型是(Any) -> Any 。 上面的定义编译。 Kotlin编译器没有任何问题,看到x1是一个Any

虽然尝试调用fn1本身不起作用。 …和编译器说明了原因: fn1是一个((Any) -> Any) -> Any函数,不能用作(Any) -> Any 。 为什么不行? 那么,因为有人可能会援引论点!

为便于讨论,我们创建第二个函数,与第一个函数非常相似:

 val fn2 = {x2: (Any) -> Any -> x2("foo")} 

它也编译,很好。 现在这个问题归结为:

为什么不工作: fn2(fn1)

但在这一点上应该是显而易见的。 如果这个调用起作用(不管涉及多少applyinvoke欺骗),调用x2 (在fn2内部)的尝试是行不通的,因为x2fn1的别名。 这是一个调用fn1的参数"foo" ,它期望一个函数。

tl; dr:函数在它们的参数类型中是相反的