Ответ 1
Простые правила
Существует два правила, определяющие порядок оценки выражения 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)
Mutable Objects: Слово предостережения
Группирование делает совершенный математический смысл, если методы +++
и ***
не имеют побочных эффектов. Рассмотрим:
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)
, как и ожидалось.