非方法的Eta扩展适用于字段,但不适用于局部变量

时间:2015-12-09 12:48:16

标签: scala

以下代码几乎不言自明:

class EtaExpansionOnNonMethods { // or object
    val zero = 0
    val zeroEta = zero _ // compiles: () => Int

    def f {
        val one = 1
        val oneEta = one _ // compilation error
    }
}
Error:(7, 18) _ must follow method; cannot follow Int
    val oneEta = one _
                 ^

为什么eta扩展在例如允许Int字段(导致() => Int)但不在Int局部变量上(导致编译错误)?我使用的是2.11.7版本。

1 个答案:

答案 0 :(得分:4)

这是因为val成员实际上已经编译为类似getter / setter的方法,例如运行javap EtaExpansionOnNonMethods.class,你可以从运行scalac获得:

E:\EtaExp>"C:\Program Files\Java\jdk1.8.0_51\bin\javap" EtaExpansionOnNonMethods.class
Compiled from "EtaExp.scala"
public class EtaExpansionOnNonMethods {
  public int zero();
  public EtaExpansionOnNonMethods();
}

请注意,如果您要将成员声明为private[this] val zero = 0,并将其编译为最终字段,则会在尝试eta扩展局部变量或值时获得完全相同的错误。

最后,一般的前提仍然是:你可以在方法上使用eta-expansion,即使这些方法并不是真正明确的。 :)