为什么部分应用函数推迟Scala中的类实例化?
想象一下这段代码:
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扩展: 如果e是方法类型或者e是按名称调用参数,则表达式e _是格式良好的.如果e是带参数的方法,则e _表示通过eta扩展转换为函数类型. eta扩展的算法在§6.26.5中给出,您可以遵循该算法为表达式new Foo().x1 _提供以下替换: { val x1 = new Foo(); (y1: Int) => x1.(y1); } 这意味着当使用eta扩展时,所有子表达式都在转换发生的位置进行评估(如果我已正确理解短语“maximal sub-expression”的含义)并且最终表达式是创建一个匿名函数. 在第二个示例中,那些额外的括号表示编译器将查看§6.23(特别是“匿名函数的占位符语法”)并直接创建匿名函数. 表达式(语法类别Expr)可以在标识符合法的位置包含嵌入的下划线符号_.这样的表达式表示匿名函数,其中下划线的后续出现表示连续的参数. 在这种情况下,并遵循该部分中的算法,您的表达式最终是这样的: (x1: Int) => new Foo().foo(x1) 差异是微妙的,正如@Antoras所解释的那样,实际上只会出现副作用代码. 请注意,对于涉及按名称调用代码块的情况,正在进行错误修正(例如,参见this question,this bug和this bug). 后记:在这两种情况下,匿名函数(x1:Int)=>托托扩大到 new scala.Function1[Int,Int] { def apply(x1: Int): Int = toto } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |