Scala 中的方法执行难题

发布于 2024-12-17 17:37:52 字数 519 浏览 0 评论 0原文

首先我声明一个类:

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中的一样吗?

First I declare a class:

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
  }
}

Now I execute the expression in REPL:

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

and it outputs

enter image description here

But why doesn't the method *** go first? Isn't the priority of *** higher than +++? And how about Java and C? Is it the same as in Scala?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

流星番茄 2024-12-24 17:37:52
op1 +++ op2 +++ op3 *** op4

相当于

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

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

对于 C 或 Java 中的 op1 + op2 + op3 * op4 也是如此。

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

is equivalent to

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

since method calls are left-associative. Thus first (op1 +++ op2) is evaluated, since it's the first operand to the second +++. Then the second operand, (op3 *** op4) is evaluated. And finally, the outermost operator is evaluated.

The same would be true for op1 + op2 + op3 * op4 in C or Java.

作妖 2024-12-24 17:37:52

简单规则

有两条规则决定 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)

Simple Rules

There are two rules that determine the order of op1 +++ op2 +++ op3 *** op4 expression evaluation:

Firstly since an operator starting with * takes precedence over an operator starting with + the expression is transformed into:

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

Secondly since there are multiple operators of the same precedence that appear side by side (op1 +++ op2 +++ ...) they are grouped left to right:

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

Example

Consider the following expression:

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

Following the same two simple rules it will be evaluated as:

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

Another Example

Alternatively let's apply the same two rules to op1 +++ op2 +++ op3 +++ op4 *** op5 *** op6:

Operators starting with * have precedence over operators starting with +:

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

Then group operators with the same precedence left to right:

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

Mutable Objects: a Word of Caution

The grouping makes perfect mathematical sense provided the +++ and *** methods do not have any side effects. Consider:

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

Intuitively the expression should return an object holding 5. However, because of the unfortunate side effects that +++ and *** methods produce in the original code sample (both modify the value stored within the object) the expression will result in an object holding 12 instead of expected 5.

That's why it's best to rely exclusively on immutable objects when constructing such expressions:

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)
  }  
}

The Op(1) +++ Op(2) +++ Op(1) *** Op(2) expression will result in Op(5), as expected.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文