gpt4 book ai didi

scala - 为什么部分应用函数会延迟 Scala 中的类实例化?

转载 作者:行者123 更新时间:2023-12-04 15:14:18 24 4
gpt4 key购买 nike

想象一下这段代码:

class Foo {
println("in Foo")

def foo(a: Int) = a + 1
}

现在,如果我们调用:
new Foo().foo _

Foo 类的实例将按预期创建:
in Foo
res0: (Int) => Int = <function1>

但是,如果我们调用它:
new Foo().foo(_)

Foo 的构造函数不会被调用:
res1: (Int) => Int = <function1>

如果我们接着说:
res1(7)

那是 Foo 被实例化的时候:
in Foo
res2: Int = 8

为什么 Eta 扩展与部分函数应用程序在类实例化方面有所不同?

最佳答案

男孩,这是一个微妙的,但据我所知,它遵循 Scala spec完全地。我将引用规范的 2.9 版。

对于您的第一个示例:正如您正确地说的那样,您通过方法值的特殊情况(第 6.7 节)看到 eta 扩展:
The expression e _ is well-formed if e is of method type or if e is a call-by-name parameter. If e is a method with parameters, e _ represents e converted to a function type by eta expansion.
eta 扩展的算法在第 6.26.5 节中给出,您可以按照它对表达式 new Foo().x1 _ 进行以下替换:

{
val x1 = new Foo();
(y1: Int) => x1.(y1);
}

这意味着当使用 eta 扩展时,所有子表达式都在发生转换的点进行评估(如果我正确理解了短语“最大子表达式”的含义)并且最终表达式是创建一个匿名函数。

在您的第二个示例中,那些额外的括号意味着编译器将查看第 6.23 节(特别是“匿名函数的占位符语法”)并直接创建一个匿名函数。
An expression (of syntactic category Expr) may contain embedded underscore symbols _ at places where identifiers are legal. Such an expression represents an anonymous function where subsequent occurrences of underscores denote successive parameters.
在这种情况下,按照该部分中的算法,您的表达式最终会是这样的:
(x1: Int) => new Foo().foo(x1)

差异是微妙的,正如@Antoras 很好解释的那样,实际上只有在存在副作用代码的情况下才会显示出来。

请注意,对于涉及按名称调用代码块的情况,正在进行错误修复(例如,参见 this questionthis bugthis bug )。

后记 : 在这两种情况下,匿名函数 (x1:Int) => toto扩大到
new scala.Function1[Int, Int] {
def apply(x1: Int): Int = toto
}

关于scala - 为什么部分应用函数会延迟 Scala 中的类实例化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10761994/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com