Простые правила
Существует два правила, определяющих порядок 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)
Изменяемые объекты: слово предостережения
Группировка имеет совершенный математический смысл, если методы +++
и ***
не имеютлюбые побочные эффекты.Обратите внимание:
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)
}
}
The Op(1) +++ Op(2) +++ Op(1) *** Op(2)
выражение приведет к Op(5)
, как и ожидалось.