【问题标题】:Eta-expansion on non-methods works for fields but not for local variables非方法的 Eta 扩展适用于字段,但不适用于局部变量
【发布时间】:2015-12-09 12:48:15
【问题描述】:

下面的代码几乎是不言自明的:

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

    def f {
        val one = 1
        val oneEta = one _ // compilation error
    }
}
错误:(7, 18) _ 必须遵循方法;不能跟随 Int val oneEta = 一 _ ^

为什么在 e.g. 上进行 eta-expansion允许Int 字段(导致() => Int)但不在Int 局部变量上(导致编译错误)?我使用的是 2.11.7 版本。

【问题讨论】:

    标签: scala


    【解决方案1】:

    那是因为 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,即使这些方法不是很明确。 :)

    【讨论】:

    • 你能引导我到 SLS 中定义此行为的部分吗?
    • @xehpuk 老实说,我在规范中找不到任何说明vals 应该如何编译的内容,所以我不确定它是否记录在某个地方(我只是找不到它现在),或者如果它是一个实现细节。
    猜你喜欢
    • 2019-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    • 2013-12-17
    相关资源
    最近更新 更多