- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
虽然随问题提供的代码相当琐碎,但问题侧重于类型安全的更一般方面:
让我们有一个像这样的 lambda 函数:
{it: (Any) -> Any -> it(it)}
它接受另一个 lambda 并以自身作为参数执行它。因此,让我们做一些显而易见的事情,并以自身作为参数调用它:
{it: (Any) -> Any -> it(it)}.apply { this.invoke(this) }
但这并不像我想的那样有效:我在编译时收到以下错误:
类型不匹配:推断类型是 ((Any) -> Any) -> Any 但 (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) }
区别在哪里?
最佳答案
好的,正如我在评论中所说,在提出这个问题的方式中存在很多无关紧要的混淆。让我们从清理其中的一些开始:
val fn1 = {x1: (Any) -> Any -> x1(x1)}
fn1
的类型是((Any) -> Any) -> Any
. x1
的类型是(Any) -> Any
.上面的定义编译。 Kotlin 编译器可以毫不费力地看到 x1
是一个 Any
.
尝试调用 fn1
但是,就其本身而言,这是行不通的。 ... 编译器准确说明了原因:fn1
是一个 ((Any) -> Any) -> Any
的函数并且不能用作 (Any) -> Any
.为什么那行不通?好吧,因为有人可能会引用这个论点!
为了便于讨论,让我们创建第二个函数,与第一个函数非常相似:
val fn2 = {x2: (Any) -> Any -> x2("foo")}
它也可以编译,就好了。现在,整个问题归结为:
为什么这行不通:fn2(fn1)
但在这一点上应该是显而易见的。如果该调用有效(无论涉及多少 apply
或 invoke
诡计),则尝试调用 x2
(在 fn2
内)无法工作,因为 x2
是 fn1
的别名.这是对 fn1
的调用使用参数 "foo"
,它需要一个函数。
tl;dr:函数的参数类型是逆变的
关于lambda - Kotlin Any 和 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46162015/
我是一名优秀的程序员,十分优秀!