В Ruby результат выражения определяется так называемым приоритетом оператора. Это набор правил, определяющих, как Ruby решает, какие операнды принимает каждый оператор. Операнды — это просто значения, используемые оператором. Они являются результатом вычисления выражений.
«Сначала смотри, потом думай, а потом тестируй. Но всегда смотрите сначала. В противном случае вы увидите только то, что ожидали».
- Дуглас Адамс
Пример приоритета Ruby
Когда люди оценивают выражения, они обычно начинают слева и продвигаются вправо (это математически неверно, но так инстинктивно делает большинство людей). Например, работая слева направо, следующее выражение дает результат 300:
10 + 20 * 10 = 300
Это вызвано тем фактом, что когда мы прибавляем 10 к 20, мы получаем 30, а затем умножаем это на 10, чтобы получить 300. Когда вы просите Ruby выполнить те же вычисления, вы получаете совсем другой результат:
irb(main):003:0> 10 + 20 * 10 => 210
Это связано с приоритетом оператора. В Ruby есть набор правил, указывающих, как оценивать операторы в выражении. Ясно, что Ruby дает оператору умножения (*) приоритет над оператором сложения (+).
Преобладающий приоритет
Встроенный в Ruby приоритет можно переопределить, заключив часть выражения с более низким приоритетом в круглые скобки. В качестве примера:
(10 + 20) * 10 => 300
Фрагмент выражения, заключенный в круглые скобки в предыдущем примере, вычисляется до умножения с более высоким приоритетом. Подобно тому, как скобки всегда оцениваются первыми при выполнении математических операций вручную.
Таблица приоритетов
Если вам нужно узнать приоритет операций, используемый Ruby, обратитесь к таблице ниже. В таблице перечислены все операторы в порядке возрастания приоритета:
Операторы со значением «Да» в столбце «Метод» — это методы, которые можно переопределить.
Порядок оценки
Возможно, вы где-то слышали или читали, что приоритет определяет порядок, в котором вычисляются выражения. Однако процесс оценки сложнее, чем просто решить, что будет оцениваться в первую очередь. На самом деле приоритет — это только часть истории Ruby; другие части - это вычисление слева направо, вычисление справа налево, короткое замыкание и троичные выражения. Каждый из них уникальным образом изменяет порядок операций. Обсуждение точных различий выходит за рамки этой статьи, но я призываю вас поэкспериментировать с ними и убедиться в этом самим.
Один интересный момент заключается в том, что хотя такие блоки, как do...end
и {}
, имеют самый низкий приоритет, они не эквивалентны. Приоритет {}
немного выше, чем do...end
, и поэтому вы можете получить разные результаты в зависимости от того, какой тип блока вы используете.
Заключение
Понимание приоритета операторов является ключом к написанию кода, который ведет себя так, как вы ожидаете. Если вы сомневаетесь, всегда используйте круглые скобки, чтобы переопределить приоритет по умолчанию.