не может понять результат логического оператора рубина

В Ruby разумно найти такой код:

a = 1 and b = 2 and c = 3
print "a = #{a}, b = #{b}, c = #{c}\n"

получает результат:

a = 1, b = 2, c = 3

но я не могу понять, почему такой код:

a = 1 && b = 2 && c = 3
print "a = #{a}, b = #{b}, c = #{c}\n"

результат:

a = 3, b = 3, c = 3

Может ли кто-нибудь прояснить это для меня?


person Huibin Zhang    schedule 02.09.2013    source источник
comment
Оба фрагмента кода просто дают мне SyntaxError. Я не получаю тех результатов, которые вы видите.   -  person Jörg W Mittag    schedule 03.09.2013
comment
Спасибо за правку Андрей, лучше выглядит   -  person Huibin Zhang    schedule 03.09.2013


Ответы (2)


Речь идет о более высоком приоритете оператора &&, чем and:

a = 1 && b = 2 && c = 3

эквивалентно

a = (1 and b = (2 and c = 3))

что приводит к

  1. 3 присвоено c
  2. (2 и 3), в результате чего 3 присваивается b
  3. (1 и 3), что приводит к 3, наконец, присваивается a
person David Unric    schedule 02.09.2013
comment
Это действительно полезно, спасибо Дэвид! - person Huibin Zhang; 03.09.2013
comment
Вы не объясняете, почему 2 && 3 == 3 - person Borodin; 03.09.2013
comment
@Borodin Logical and оценивает свой правый аргумент, только если левый операнд оценивается как true, что допустимо для любого объекта, кроме nil или false. Правый операнд тогда является результатом выражения. Но я не думаю, что это нужно упоминать в ответе на вопрос OP. - person David Unric; 03.09.2013
comment
@Borodin Ваша вставка самых внутренних пар в моем ответе нахожу совершенно излишней. - person David Unric; 03.09.2013
comment
@DavidUnric: Честно говоря, это ваш ответ. Но мы говорим здесь о приоритете операторов, и я не вижу причин, по которым 2 and c = 3 не равно (2 and c) = 3. - person Borodin; 03.09.2013
comment
@DavidUnric: Хорошо, тогда почему логические и оценивают свой правый аргумент только в том случае, если левый операнд оценивается как истина? - person Borodin; 03.09.2013

Помимо приоритета операндов, такое поведение является результатом оценки короткого замыкания < / em> логических операторов.

При проверке and, если первый операнд оказывается ложным, тогда нет причин для оценки второго. Следовательно, значение a and b рассчитывается как a ? b : a.

Точно так же оператор or заключает контракт с a ? a : b.

Эти оптимизации работают логически нормально, когда нас не волнует конкретное возвращаемое значение, а только то, истинно оно или ложно. Но он также позволяет использовать полезные идиомы программирования, такие как

( list = list || [] ) << item

который работает, потому что list = list || [] оценивается как list = list (бездействие), если list истинно (не ноль), или list = [] (создание нового пустого массива), если list уже был инициализирован, и поэтому "истинно" < / em>.

Таким образом, выражение типа 2 and (c = 3) оценивается как 2 and 3 или 2 ? 3 : 2, поэтому 3.

person Borodin    schedule 02.09.2013