Scala中的方法执行难题

爱国者*_*爱国者 5 c java scala operator-precedence

首先我宣布一个类:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

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

op1 +++ op2 +++ op3 *** op4
Run Code Online (Sandbox Code Playgroud)

它输出

在此输入图像描述

但为什么这个方法不是***先行?是不是优先级***高于+++?Java和C怎么样?它和Scala一样吗?

Kim*_*bel 13

op1 +++ op2 +++ op3 *** op4
Run Code Online (Sandbox Code Playgroud)

相当于

((op1 +++ op2) +++ (op3 *** op4))
Run Code Online (Sandbox Code Playgroud)

因为方法调用是左关联的.因此首先(op1 +++ op2)进行评估,因为它是第二个的第一个操作数+++.然后(op3 *** op4)评估第二个操作数.最后,评估最外层的运算符.

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


Vla*_*dim 5

简单的规则

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

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

op1 +++ op2 +++ (op3 *** op4)
Run Code Online (Sandbox Code Playgroud)

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

(op1 +++ op2) +++ (op3 *** op4)
Run Code Online (Sandbox Code Playgroud)

请考虑以下表达式:

op1 +++ op2 +++ op3 +++ op4 *** op5
Run Code Online (Sandbox Code Playgroud)

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

((op1 +++ op2) +++ op3) +++ (op4 *** op5)
Run Code Online (Sandbox Code Playgroud)

另一个例子

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

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

op1 +++ op2 +++ op3 +++ (op4 *** op5 *** op6)
Run Code Online (Sandbox Code Playgroud)

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

((op1 +++ op2) +++ op3) +++ ((op4 *** op5) *** op6)
Run Code Online (Sandbox Code Playgroud)

可变对象:谨慎的话语

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

op1 +++ op2 +++ op1 *** op2
Run Code Online (Sandbox Code Playgroud)

直观地表达应返回的物体保持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)
  }  
}
Run Code Online (Sandbox Code Playgroud)

Op(1) +++ Op(2) +++ Op(1) *** Op(2)表达式将导致Op(5),符合市场预期.