Приоритет оператора для And/&& в Ruby
У меня есть вопрос относительно ключевых слов и /&/= в Ruby.
В документах ruby говорится, что приоритет для указанных ключевых слов: (1) & &, (2) =, (3) и.
У меня есть этот фрагмент кода, который я написал:
def f(n)
n
end
if a = f(2) and b = f(4) then
puts "1) #{a} #{b}"
end
if a = f(2) && b = f(4) then
puts "2) #{a} #{b}"
end
Вывод:
1) 2 4 [Ожидается]
2) 4 4 [ Почему?]
По какой-то причине использование && заставляет а и b оценивать до 4?
Ответы
Ответ 1
Я не совсем понимаю вопрос, который вы задаете. Я имею в виду, что вы уже сами дали ответ, прежде чем задавать вопрос: &&
привязывается более жестко, чем =
, а and
связывается менее плотно, чем =
.
Итак, в первом случае выражение оценивается следующим образом:
( a=f(2) ) and ( b=f(4) )
( a= 2 ) and ( b=f(4) )
2 and ( b=f(4) ) # a=2
2 and ( b= 4 ) # a=2
2 and 4 # a=2; b=4
4 # a=2; b=4
Во втором случае оценка выглядит следующим образом:
a = ( f(2) && ( b=f(4) ) )
a = ( 2 && ( b=f(4) ) )
a = ( 2 && ( b= 4 ) )
a = ( 2 && 4 ) # b=4
a = 4 # b=4
4 # b=4; a=4
Ответ 2
Причина проста: приоритет. Как вы говорите, порядок:
Так как &&
имеет приоритет над =
, оператор вычисляется следующим образом:
if a = (f(2) && (b = f(4))) then
Результат:
if a = (2 && 4) then
Когда x
и y
являются целыми числами, x && y
возвращает y
. Таким образом, 2 && 4
приводит к a = 4
.
Для сравнения, первый из них оценивается следующим образом:
if (a = f(2)) and (b = f(4)) then
Ответ 3
От Программирование Ruby 1.9:
Единственное различие в двух формах - приоритет (and
связывается ниже &&
).
Ответ 4
Я не знаю конкретных правил, которые могут помочь в этой ситуации, но позвольте использовать приоритеты операций.
Используя правила приоритетов, мы можем разделить вычисление второго выражения на несколько шагов
1 f(2) && b => expr1
2 expr1 = f(4) => expr2
3 a = expr2
Очевидно, что на шаге 2 мы получаем неверную ситуацию - в левой части = is rvalue - временный объект, который нельзя присвоить никаким значением. Я предполагаю, что синтаксический анализатор нарушает правила приоритетной оценки выражений при столкновении с такими ситуациями.
Более подробную информацию о вычислениях выражений можно найти здесь
Ответ 5
если вы измените свой код таким образом, вы получите то, что ожидаете
def f(n)
n
end
if (a = f(2) and b = f(4)) then
puts "1) #{a} #{b}"
end
if (a = f(2) and b = f(4)) then
puts "2) #{a} #{b}"
end
1) 2 4
2) 2 4