在“Scala编程”一书中(Martin Odersky,第2版),他们给出了运算符优先级表(这里不完整):
* / %
+ -
:
= !
< >
&
^
|
因此,如果运算符的第一个字符在此表中的位置高于另一个运算符的第一个字符,则首先计算前一个运算符。
根据该代码应打印yy
,但打印出x
:
def x() = { print('x'); true }
def y() = { print('y'); true }
x || y && y // prints `x` but should `yy`
我的理解是,如果表 | 中的&amp; 更高,则必须先评估它。就像 * 优先于 + 一样,所以在x + y * y
中,最后一个语句首先被evalueted。
修改:
另请查看此代码
def x() = { print('x'); 1 }
def y() = { print('y'); 3 }
x == x + y * y // xxyy
看起来它从左到右评估它们,但根据表格“解决”它们。
答案 0 :(得分:3)
原始版本:
x || y && y
应用优先级:
x || (y && y)
(注意,如果优先权被颠倒,那将是(x || y) && y
。)
现在,您期望在(y && y)
之前评估x
,但Scala始终从左到右进行评估(请参阅language spec的§6.6)。并且,正如其他人所提到的,||
是一个短路运算符,因此如果第一个操作数返回true,则第二个操作数甚至不会被评估。
另一种思考方式是两个方法调用,其中两个方法的第二个操作数是按名称传递的:
or (x, and(y, y))
def or(a: Boolean, b: => Boolean): Boolean = if (a) true else b
def and(a: Boolean, b: => Boolean): Boolean = if (!a) false else b
在从左到右的评估模型中,x
总是首先评估,然后可能y
两次。
如果你还没有这样做,你可以在Coursera跟随Martin Odersky的函数式编程课程,在那里他将在第1或第2讲中讨论这个主题。
你的第二个例子相当于
add(x, mult(y, y))
def add(a: Int, b: Int) = a + b
def mult(a: Int, b: Int) = a * b
始终首先评估 x
,然后评估y
两次。
答案 1 :(得分:2)
它打印x
,因为x()
调用返回true
,如果||
逻辑运算符,如果左边部分返回true,则不计算右边部分。要计算它,请使用|
,即使左侧部分为true
,也会评估正确的部分
<强>更新强>
布尔值的示例不好,因为如果使用布尔值,则使用所谓的“短路”评估,如果左侧部分是{{{sc},则scalac甚至不会查看or
表达式的第二部分1}}。想想这个操作就像:
true