Reputation: 1224
In the book "Programming in Scala" (Martin Odersky, 2nd edition) they give this operator precedence table (not complete here):
* / %
+ -
:
= !
< >
&
^
|
So that if the first character of an operator has a higher position in this table that the first character of another operator, the former operator is evaluated first.
According to that this code should print out yy
, but it prints out x
:
def x() = { print('x'); true }
def y() = { print('y'); true }
x || y && y // prints `x` but should `yy`
My understanding is that if & is higher in the table that |, it must be evaluated first. It is like * has precedence over +, so in x + y * y
, the last statement is evalueted first.
EDIT:
Also look at this code
def x() = { print('x'); 1 }
def y() = { print('y'); 3 }
x == x + y * y // xxyy
Look like it evaluates them from left to right but "solves" them according to the table.
Upvotes: 0
Views: 1102
Reputation: 3982
Raw version:
x || y && y
With precedence applied:
x || (y && y)
(Note, if the precedence was reversed it would be (x || y) && y
.)
Now, you are expecting (y && y)
to get evaluated before x
, but Scala always evaluates left-to-right (see §6.6 of the language spec). And, as others have mentioned, ||
is a short-circuiting operator, so the the second operand is not even evaluated if the first operand returns true.
Another way to think of it is as a two method calls, where the second operand of both is pass-by-name:
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
Under the left-to-right evaluation model, x
is ALWAYS evaluated first, then maybe y
twice.
If you haven't already done so, you could follow Martin Odersky's functional programming course on Coursera where he talks about this very subject in lecture 1 or 2.
Your second example is equivalent to
add(x, mult(y, y))
def add(a: Int, b: Int) = a + b
def mult(a: Int, b: Int) = a * b
x
is always evaluated first, then y
, twice.
Upvotes: 3
Reputation: 21567
It prints x
because x()
call returns true
and in case of ||
logic operator if left part return true, the right part is not computed. To compute it use |
then, even if left part is true
the right part will be evaluated
Updated
Example with boolean is not good, because in case with booleans so called "short-circuit" evaluation is used and scalac won't even look at the second part of or
expression if the left part is true
. Think of this operation like:
def || (a: => Boolean) = ???
Upvotes: 2