加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

为什么部分应用函数推迟Scala中的类实例化?

发布时间:2020-12-16 18:50:42 所属栏目:安全 来源:网络整理
导读:想象一下这段代码: class Foo { println("in Foo") def foo(a: Int) = a + 1} 现在,如果我们调用: new Foo().foo _ 正如预期的那样,将创建类Foo的实例: in Foores0: (Int) = Int = function1 但是,如果我们调用它: new Foo().foo(_) Foo的构造函数不会被
想象一下这段代码:

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
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读