Операторы '&&' и 'and' в Ruby

    На одном собеседовании меня спросили: «когда ты пишешь на Ruby, ты пользуешься оператором 'and' или двумя символами амперсанда '&&' для обозначения логического 'И' ?». На самом деле, я по старой привычке всегда ставил два символа амперсанда '&&' и никогда не задумывался об этом. Так и ответил, мне сказали «Хорошо».

    А вы не смотря под cut можете внятно объяснить разницу между 'and' и '&&' в Ruby?


    Допустим у нас есть следующий код.
    total = user_messages.empty? and user_messages.total


    И какое значение будет у total? Количество сообщений у пользователя? Нет! Все дело в том, что интерпретатор прочитает это так:
    (total = user_messages.empty?) and user_messages.total



    Значит total станет true или false. Это ведь совсем не то, что вы хотели! Почему так происходит? Просто потому, что есть таблица приоритета операторов в Ruby. Изучив её, понимаем, что можно использовать оператор &&.
    Две следующие строки кода абсолютно одинаковы.

    total = user_messages.empty? && user_messages.total
    total = (user_messages.empty? && user_messages.total)



    Аналогичная история с операторами or и ||.
    Присмотритесь к своему коду…

    P.S. А вот еще пример для окончательного понимания (или непонимания)
    irb(main):001:0> x=1
    => 1
    irb(main):002:0> y=2
    => 2
    irb(main):003:0> x || y && nil
    => 1
    irb(main):004:0> x or y and nil
    => nil

    Поделиться публикацией

    Комментарии 77

      +20
      Я скобки всегда ставлю, чтобы с приоритетами не облажаться
        0
        Дело вкуса конечно, мне кажется что код без скобок как-то чище.
          +2
          Скорее правило хорошего тона, тем более на этапе условной компиляции может изменяться приоритет — так что еще и от ошибок спасает в определенных случаях.
          +3
          Так же стараюсь всегда ставить скобки, уже как привычка и разобраться потом легче. Хотя иногда в условие, случайно, как поставишь вместо "==" символ "=", а потом сидишь на измене от непонятного бага =)
            +5
            от этого противоядие такое
            if( $a== 1) меняем на if ( 1 == $a)
              +1
              а как бороться с if ($a == $b)? :)
                +3
                $a и $b местами меняли? :))
                Бороться если только силами IDE.
                Скажем, в зенд студио analyze code (shift+ctrl+a) выдаст «Assignment in condition (line **)»
                  0
                  это был скорее риторический вопрос, шутка юмора такая:)
                  0
                  К сожалению, это косяк на уровне языка. С одной стороны у некоторых языков есть решение в виде запрета присваивания в операторе if, но с другой — это накладывает определенные ограничения, например при одновременной проверке выполнения функции с присваиванием ее булевой переменной: if(proccessed = process_something()), пусть даже подобные конструкции являются плохим стилем.
                    0
                    > присваивания в операторе if
                    Во всех условиях конечно же. Не только в if.
                      0
                      тут не так все однозначно, иногда (ну очень редко) надо проверять именно реакцию после присвоения, а с вот таким прийдется делать костыли (
                        0
                        в таких случаях это просто удобно:
                        if ( ($a = get_func()) && ($pos = strpos("..",$a)) !== false )
                        // using $pos
                  +2
                    0
                    спасибо, улыбнуло :)
                –2
                скобки дополнительная операция, вы тормозите и так тормозной ruby ;)
                  0
                  Ну вот, оптимизация на спичках :)
                +3
                >> А вы не смотря под cut можете внятно объяснить разницу между 'and' и '&&' в Ruby?
                Да, главное не только в руби, во многих языках так.
                  –3
                  Да, в PHP то же самое :).
                  +1
                  а я просто никогда не использую or и and — гораздо проще написать || и && :)
                    0
                    Я тоже никогда не пользовался, но вот после этого собеседования очень захотелось узнать разницу.
                      +2
                      Оффтоп: я вот ещё не совсем понял, много собеседований это признак хорошего специалиста или нет? ;)
                        +4
                        возможно, это признак общительного человека :)
                    0
                    А если мне нужно именно and и я знаю как его использовать? Вопрос не вполне корректный
                      +1
                      Ну тогда вы — молодец! Я же не утверждаю, что нужно использовать именно &&, я просто хочу показать разницу.
                        0
                        Вашу цель я понял, это я именно к вопросу на собеседовании. Они оценили именно, то что вы используете && как «хорошо» без всяких уточнений
                      +1
                      Главное не забывать, что ваш код кто-нибудь будет читать.
                        +2
                        И это «кто-нибудь» может быть и будете вы сами.
                        –1
                        Меня когда то спросили разницу " и '
                        К сожалению, я тогда не знал…
                        И про && и and узнал только что :)
                        Спасибо!
                          0
                          Рад, что помог.
                          –4
                          ага, давайте руби вей сюда по главам перепишем
                            +2
                            Простите, но я не хотел сюда ничего переписывать, просто написал об интересном моменте.
                            +3
                            Говорили мне в 2006 году: в Руби слишком много магии. Хорошо, что прислушался.
                              +3
                              Магия эта очень приятная. И чем больше её изучаешь, тем более приятной она становится.
                                +3
                                Согласен, что приятная, мне очень нравился Руби и нравится до сих пор, но пишу я, тем не менее, на Питоне и не жалею.
                                +6
                                Говорили парни, которые работали на PHP? Вам соврали.
                                  0
                                  В PHP, если я не ошибаюсь, с and и && точно такая же «магия».

                                  А с комментатором выше не согласен, думаю, напрасно Вы тогда прислушались:)
                                    0
                                    В PHP ровно эти же конструкции, ровно с теми же приоритетами.
                                      0
                                      релакс, это был подкол
                                      0
                                      Хорошие парни говорили, грамотные, которые сейчас не пишут на PHP очень давно и работают в Яндексе. А дело не в том соврали ли нет, а в том, что я с ними согласен.
                                        0
                                        [...] не пишут на PHP очень давно и работают в Яндексе.

                                        Тут закрадывается подозрение на причинно-следственную связь (не удержался).

                                        А дело не в том соврали ли нет, а в том, что я с ними согласен.

                                        Любая точка зрения имеет право на существование.
                                      0
                                      нет в ruby магии, вас обманули
                                      +7
                                      Вообще не понимаю зачем нужна поддержка 'and' и 'or' в языках — разница в приоритетах только ухудшает понимание между разработчиками одного кода и с течением времени. Имхо это пример того, как малюсенькая свобода в языке увеличивает шансы сделать багу.
                                        0
                                        В чём-то я с вами согласен.
                                          0
                                          Язык надо знать.
                                            +3
                                            Мне кажется, это идет откуда-то из перловых времен, когда были модны конструкции типа
                                            $vip = get_very_important_peremennaya(...) or die «Ah uh!»
                                              +1
                                              В данном случае это не свобода. Это читабельность и выразительность.
                                              –6
                                              ДААА… ХАБР УЖЕ НЕ ТОТ!
                                                –4
                                                Нет, ну нельзя такие вещи постить на Хабре. Что будет если каждый будет писать о новых классных операторах? А в руби много магии о которой можно писать :)
                                                Это же не дневник!
                                                  +1
                                                  Никогда не писал на Ruby, и мне его хвалили (хотя синтаксис не совсем в моем вкусе).
                                                  Но сдается мне, что это некоторая избыточность языка, которая может привести к ошибке. Хотя, вполне возможно, что есть у каждого оператора своя область применения, но я ее не вижу.
                                                    0
                                                    В руби много дублирующихся методов. Это сделано для того, что, чтобы разные люди с разными предпочтениями чувствовали себя комфортно.
                                                      +1
                                                      Оно, конечно, похвально. Но когда дойдет до момента «читать чужой код» станет тяжело — не факт, что ты будешь чувствовать себя комфортно.
                                                      Но осуждать не берусь, очень хитрый метод заманивания разработчиков :) Саму идею одобряю.
                                                        0
                                                        Принципе наименьшего удивления — часть «пути Руби». Конечно, это может раздражать некоторых пользователей, но для них есть другие отличные языке, где «только один способ сделать что-то».
                                                        В общем нужно принимать руби таким каков он есть и придерживаться здравого смысла при написании программ :)
                                                          0
                                                          Любой код, написанный на Руби более-менее здравомыслящим человеком читается очень просто, даже если язык видишь в первый раз.
                                                            0
                                                            Не скажите. Зная Си, понятно, что такое && или ||. А зная английский, очевидно, что такое and и or. В то же время, зная стандартные map, filter, reduce, очень непросто догадаться, что рубишные collect, select, reject делают то же самое. Совсем неочевидно.
                                                        0
                                                        Я до этого немного писал на перле, и меня сильно раздражал его чрезмерно лаконичный синтаксис — слишком много возможностей для ошибки и, главное, когда читаешь свой же код через полгода, приходится вспоминать что и зачем ты сделал так, как следствие, при командной работе нужно очень четко договариваться о стандартах кодирования. Собс-но одна из причин из-за чего я захотел расстаться с перлом.
                                                        Посмотрел на руби — увидел похожу вольницу — поэтому как-то сразу охладел к нему.
                                                        Хотя язык толковый. Иногда возникает желание за него взяться.
                                                          0
                                                          «Perl is write-only language» © Не помню.
                                                          +1
                                                          вроде бы это идиома от perl'а, там достаточно часто бывает что-то вроде:

                                                          a = do_something or die('все плохо')

                                                          Это обходится правильным стилем кодирования в котором прописано, что 'and' и 'or' использовать нельзя без утверждения другим разработчиком. То же и про глобальные переменные в rails, например.
                                                            +1
                                                            Или курсами по языку для разработчика. Я всё удивляюсь, если кто-то считает язык слишком сложным для себя, то может и не надрываться? Изучить что полегче.
                                                              –1
                                                              Судя по Ваши постам вы явно отлично знаете Супер Сложные Языки аля PHP и Ruby, которые не в состоянии осилить ни один смертный разработчик… Прошу прощения за сарказм, не сдержался.
                                                              Вопрос-то не в том, что те, кто не знает таких подробностей — недочеловеки и им надо закрыть доступ к написанию кода, пока не выучат. А в том, что чем больше нюансов должен держать в голове программист — тем тяжелее ему делать свое дело и, следовательно, больше вероятность чего-то забыть и неправильно сделать. Имхо гораздо лучше, если разработчик будет держать в голове нюансы, связанные с задачей, которую ему надо сделать, а не с премудностями языка, который он использует.
                                                                0
                                                                Зря не сдержались. У меня опыт программирования на Perl был несколько лет. Три ассемблера в совершенстве за плечами. И так далее.
                                                                  +1
                                                                  Чтобы делать своё дело легко, надо это «дело» хорошо знать, чему способствует регулярное перечитывание учебников и методичек. Тогда все эти «премудрости языка» будут помогать, а не мешать решению задачи.

                                                                  Поставить диагноз программисту, не знающему досконально своего основного языка, очень просто — дизартрия и общее недоразвитие речи.
                                                                    +1
                                                                    «Пивная! Ещё парочку!»
                                                                      0
                                                                      Не, скорее «мы их душили-душили, душили-душили...»
                                                                +2
                                                                Зачем обходить то, что отлично работает? Как сказали выше, если вам не нравится берите то, что попроще.
                                                                use Perl or die;
                                                              0
                                                              Меня еще в школе, на уроках программирования, учитель (выходец из Индии) учил, что скобки — наше все! Ни разу это правило не подводило.
                                                                0
                                                                Похожая фигня в РНР. На RSDN'е выяснили, что приоритет операторов пришел из Perl'а. В Ruby, по всей видимости, тоже
                                                                  0
                                                                  irb(main):005:0> total = false and 10
                                                                  => false
                                                                  irb(main):006:0> total = false && 10
                                                                  => false
                                                                  irb(main):007:0> total = true and 10
                                                                  => 10
                                                                  irb(main):008:0> total = true && 10
                                                                  => 10

                                                                  что я делаю не так, где разница-то?
                                                                    0
                                                                    А, всё, понял.

                                                                    +1
                                                                    я в основном пользую && и ||

                                                                    а «and» и «or» только в следующих конструкциях:

                                                                    do_something and return…

                                                                    do_something or return…

                                                                    в первом варианте возврат в случае успеха (вернули тру) во втором в случае если вернули фолс

                                                                    второй вариант иногда так:

                                                                    do_something or raise…

                                                                      0
                                                                      Такой приоритет операторов пришел из Perl. Многие современные скриптовые языки так или иначе многое почерпнули из Perl :) PHP, Ruby и Python не исключение.

                                                                      Кстати, в Perl логические операторы && и || (а теперь еще и //) на самом деле не чисто логические. Конструкция вида $a || $b вернет значение первой переменной, которое будет истиной. Например $a = 0 || 5 присвоит $a = 5, но не $a = true :)
                                                                      Это дает дополнительную гибкость языку. Многие этого почему-то не любят, но это их право всего бояться и писать конструкции вида if (1 == $a) {...}
                                                                      Возможности и особенности языка надо знать, без этого иногда становится грустно :)
                                                                        0
                                                                        В Ruby аналогично:
                                                                        >> a = 0 || 5
                                                                        => 0
                                                                        То есть a теперь равно 0 (не забываем, что 0 в Ruby это true).

                                                                          0
                                                                          Этапять ящитаю %)
                                                                          Неожиданно )
                                                                        0
                                                                        А почему нельзя вместо этого:
                                                                        total = user_messages.empty? and user_messages.total
                                                                        написать это:
                                                                        total = user_messages.total unless user_messages.empty?
                                                                          0
                                                                          Можно.

                                                                          Вопрос был не в том, чтобы открыть для себя постфиксную форму условного оператора…
                                                                            0
                                                                            Просто в конкретно данном случае мой пример был бы (имхо) намного лучше, и не вставало бы непонятных вопросов про приоритеты. Но, несомненно, приоритеты знать нужно, у меня всегда больше наугад идет (методом тыка). Конечно, возможно это не тру-ниндзя-стайл, но намного быстрее получается.
                                                                          0
                                                                          Аналогично и для PHP.
                                                                            0
                                                                            Это учат на первом курсе программирования.

                                                                            Use &&/|| for boolean expressions, and/or for control flow. (Rule of thumb: If you have to use outer parentheses, you are using the wrong operators.)

                                                                            # boolean expression
                                                                            if some_condition && some_other_condition
                                                                            do_something
                                                                            end

                                                                            # control flow
                                                                            document.saved? or document.save!

                                                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                            Самое читаемое