Scala 中的方法执行难题
首先我声明一个类:
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
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
相当于
因为方法调用是左关联的。因此,第一个
(op1 +++ op2)
被求值,因为它是第二个+++
的第一个操作数。然后计算第二个操作数(op3 *** op4)
。最后,评估最外面的运算符。对于 C 或 Java 中的
op1 + op2 + op3 * op4
也是如此。is equivalent to
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.简单规则
有两条规则决定
op1 +++ op2 +++ op3 *** op4
表达式求值的顺序:首先,因为以 * 开头的运算符优先于以 + 开头的运算符,所以表达式转换为:
其次,由于有多个并排出现的相同优先级的运算符 (op1 +++ op2 +++ ...),它们从左到右分组:
示例
考虑以下表达式:
遵循相同的两个简单的规则将被评估为:
另一个例子
或者让我们应用与
op1 +++ op2 +++ op3 +++ op4 *** op5 *** op6
相同的两个规则:以 * 开头的运算符优先于以 + 开头的运算符:
然后将运算符分组从左到右相同的优先级:
可变对象:注意事项
只要
+++
和***
方法没有任何副作用,分组就具有完美的数学意义。考虑一下:直观上,表达式应该返回一个包含 5 的对象。但是,由于
+++
和***
方法在原始代码示例中产生了不幸的副作用(两者都会修改对象中存储的值)表达式将导致对象持有 12 而不是预期的 5。这就是为什么在构造此类表达式时最好完全依赖不可变对象:
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:
Secondly since there are multiple operators of the same precedence that appear side by side (op1 +++ op2 +++ ...) they are grouped left to right:
Example
Consider the following expression:
Following the same two simple rules it will be evaluated as:
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 +:
Then group operators with the same precedence left to right:
Mutable Objects: a Word of Caution
The grouping makes perfect mathematical sense provided the
+++
and***
methods do not have any side effects. Consider: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:
The
Op(1) +++ Op(2) +++ Op(1) *** Op(2)
expression will result inOp(5)
, as expected.