【问题标题】:The method execution puzzle in ScalaScala 中的方法执行难题
【发布时间】:2011-11-25 08:29:40
【问题描述】:

首先我声明一个类:

class Op(var x : Int) {
  def +++(op: Op) = {
    println(this.x + " +++ " + op.x)
    this.x += op.x
    this
  } 
  def ***(op: Op) = {
    println(this.x + " *** " + op.x)
    this.x *= op.x
    this
  }
}

现在我在 REPL 中执行表达式:

op1 +++ op2 +++ op3 *** op4

然后输出

但是为什么方法*** 不先行呢? ***的优先级不是比+++高吗?那么Java和C呢?它和Scala一样吗?

【问题讨论】:

  • 为什么***的优先级要高于+++?就因为它隐约看起来像乘法和加法?
  • 没有。 scala中方法的优先级由方法名的第一个字符决定。有关更多信息,请参阅第 5 章第 8 节的

标签: java c scala operator-precedence


【解决方案1】:
op1 +++ op2 +++ op3 *** op4

等价于

((op1 +++ op2) +++ (op3 *** op4))

因为方法调用是左关联的。因此第一个(op1 +++ op2) 被求值,因为它是第二个+++ 的第一个操作数。然后计算第二个操作数(op3 *** op4)。最后,评估最外层的运算符。

op1 + op2 + op3 * op4 在 C 或 Java 中也是如此。

【讨论】:

    【解决方案2】:

    简单规则

    有两个规则决定op1 +++ op2 +++ op3 *** op4表达式求值的顺序:

    首先,由于以 * 开头的运算符优先于以 + 开头的运算符,因此表达式被转换为:

    op1 +++ op2 +++ (op3 *** op4)
    

    其次,由于有多个具有相同优先级的运算符并排出现(op1 +++ op2 +++ ...),因此它们从左到右分组:

    (op1 +++ op2) +++ (op3 *** op4)
    

    示例

    考虑以下表达式:

    op1 +++ op2 +++ op3 +++ op4 *** op5
    

    遵循相同的两个简单规则,它将被评估为:

    ((op1 +++ op2) +++ op3) +++ (op4 *** op5)
    

    另一个例子

    或者,让我们将相同的两条规则应用于op1 +++ op2 +++ op3 +++ op4 *** op5 *** op6

    以 * 开头的运算符优先于以 + 开头的运算符:

    op1 +++ op2 +++ op3 +++ (op4 *** op5 *** op6)
    

    然后将具有相同优先级的运算符从左到右分组:

    ((op1 +++ op2) +++ op3) +++ ((op4 *** op5) *** op6)
    

    可变对象:注意事项

    如果+++*** 方法没有任何副作用,则分组具有完美的数学意义。考虑:

    op1 +++ op2 +++ op1 *** op2
    

    直观地说,表达式应该返回一个持有 5 的对象。但是,由于 +++*** 方法在原始代码示例中产生的不幸的副作用(都修改了存储在对象中的值),表达式将导致在一个持有 12 而不是预期的 5 的对象中。

    这就是为什么在构造此类表达式时最好完全依赖不可变对象:

    case class Op ( x: Int) {
      def +++(that: Op) = {
        println(this.x + " +++ " + that.x)
        Op(this.x+that.x)
      } 
      def ***(that: Op) = {
        println(this.x + " *** " + that.x)
        Op(this.x * that.x)
      }  
    }
    

    Op(1) +++ Op(2) +++ Op(1) *** Op(2) 表达式将按预期生成Op(5)

    【讨论】:

      猜你喜欢
      • 2018-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      • 2014-03-21
      • 2022-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多