为什么SAM规则不适用于无参数方法

时间:2018-03-06 07:27:00

标签: scala anonymous-class

:Cell

为什么sam1无法覆盖receive方法? scalac将两个特征编译为相同的代码。

// ok
val sam0: MySamWithEmptyParameter = () => 100

// doesn't work
//  val sam1: MySamWithParameterless = () => 100

trait MySamWithEmptyParameter {
  def receive(): Int
}

trait MySamWithParameterless {
  def receive: Int
}

1 个答案:

答案 0 :(得分:4)

SI-10555正是在谈论这个问题。这是一个简单的设计决策,只支持一个显式的空参数列表,即使这两个编译为一个空的参数列表无论如何。

The relevant part of the Specification says(强调我的):

  
      
  • 方法m 必须有一个参数列表;
  •   

这确实有点尴尬,因为eta扩展适用于带有空参数列表的方法。

修改

联系Lightbend的人。以下是Scala团队负责人Adrian Moors的回复:

  

最初的原因是保持规范简单,但也许我们应该重新审视。我同意令人惊讶的是它适用于def a(): Int,但不适用于您的示例。

     

在内部,完全没有定义参数列表的方法和那些(甚至是空的)方法的处理方式不同。   这导致了之前的混淆/错误 - 仅举一例:https://github.com/scala/scala-dev/issues/284

     

在2.13中,我们正在重新进行eta扩展(它将更积极地应用,但是 - ) - 插入将首先发生)。我们一直都是这样,但目前的想法是:

     
      
  • 0-ary方法被特别处理:如果期望的类型是sam-等效于Function0,我们eta-expand;否则,插入()(在dotty中,你需要显式地写(),除非方法是java定义的) - 我仍然不确定我们是否应该在这里进行eta-expand
  •   
  • 对于所有其他arities,方法引用是eta扩展的,无论期望的类型如何(如果没有类型不匹配,这可能会在重构参数的方法时隐藏错误,但忘记在任何地方应用它们。但是,从那以后函数是一等值,通过简化参考方法值来构造它们很容易。)
  •   
     

结果是我们可以弃用方法值语法(m _),因为它只是简单地编写m。 (请注意,这与占位符语法不同,如m(, _)中所示。)   (另请参阅此评论的主题:https://github.com/lampepfl/dotty/issues/2570#issuecomment-306202339