以下代码几乎不言自明:
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版本。
答案 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,即使这些方法并不是真正明确的。 :)