2013-09-26 4 views
0

В книге «Программирование в Scala» (Одерски, второе издание) они дают этот оператор старшинства таблицу (не заполняйте здесь):Приоритет операторов & и | в Scala

*/% 
+ - 
: 
= ! 
< > 
& 
^ 
| 

Так что, если первый символ оператор имеет более высокую позицию в этой таблице, сначала оценивается первый символ другого оператора, первый оператор.

Согласно, что этот код должен распечатать yy, но он печатает x:

def x() = { print('x'); true } 
def y() = { print('y'); true } 

x || y && y  // prints `x` but should `yy` 

Я понимаю, что если & выше в таблице, |, он должен быть оценен первым. Это как * имеет приоритет над +, поэтому в x + y * y последнее утверждение оценивается в первую очередь.


EDIT:

Также посмотрите на этот код

def x() = { print('x'); 1 } 
def y() = { print('y'); 3 } 

x == x + y * y  // xxyy 

Посмотрите, как он оценивает их слева направо, но «решает» их в соответствии с таблицей.

+0

Потому что во втором случае 'x' и' y' приводят к 'Int', а в случае Boolean использует другую оценочную модель – 4lex1v

+0

' '' это не то же самое, что '||', и книга не дает приоритет для логических операндов. Я предполагаю, что такой же приоритет используется как для Java, где '&&' все еще выше, чем '||', но тогда здесь работает короткое замыкание. Java также напечатает «x». – maksimov

ответ

2

Он печатает x потому x() вызов возвращает true и в случае || логического оператора, если не вернуть часть правда, правая часть не вычисляется. Для того, чтобы вычислить ее использовать | тогда, даже если левая часть true правая часть будет оцениваться

Обновленный

Пример с булевыми не является хорошим, так как в случае с Булев так называемых «коротких замыканий» оценка используется, и scalac даже не будет смотреть на вторую часть выражения or, если левая часть равна true. Думайте об этой операции, как:

def || (a: => Boolean) = ??? 
+0

Я знаю это, но это не объясняет. Для меня он не должен смотреть на ** x **, прежде чем решать ** y **. – Graduate

+0

@Graduate объясняет, это не очень хороший пример, в общем случае логические операторы используют оценку короткого замыкания в скалясе. Scala просто не будет смотреть на правую часть, если левая - true – 4lex1v

3

Raw версии:

С старшинства применяется: (. Обратите внимание, если приоритет был отменен он будет (x || y) && y)

x || (y && y) 

Теперь вы ожидаете получить (y && y), чтобы получить оценку до x, но Scala всегда оценивает слева направо (см. §6.6 из language spec). И, как отмечали другие, || является оператором короткого замыкания, поэтому второй операнд даже не оценивается, если первый операнд возвращает 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 дважды.

Если вы еще не сделали этого, вы могли бы следовать функциональному курсу программирования Одерский на , где он говорит об этом самом предмете в лекции 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

Ключевое недоразумение здесь состоит в том, что OP предполагает, что * приоритет оператора * соответствует * порядку оценки *, которого нет. – Impredicative

Смежные вопросы