Разница между «и» и && в Ruby?

Ответы:

349

andто же самое, &&но с более низким приоритетом . Они оба используют оценку короткого замыкания .

ПРЕДУПРЕЖДЕНИЕ: andдаже имеет более низкий приоритет, чем =вы, как правило, хотите избежать and. Пример, когда его andследует использовать, можно найти в Руководстве по Rails под заголовком « Избегание ошибок двойной визуализации ».

Доминик Роджер
источник
50
Было бы неплохо указать, что обычно следует использовать &&, в то время как andследует использовать только для очень конкретных случаев.
Марк-Андре Лафортун
10
Еще одно хорошее объяснение здесь: devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby .
Эндрю Маршалл
17
Из ссылки Эндрю Маршалла: «Другой способ думать and- это ifмодификатор обратного выражения: next if widget = widgets.popстановится widget = widgets.pop and next. Это отличный способ выразить это, действительно заставил его« щелкнуть »в моей голове. (И orпохоже на обратный unlessмодификатор.)
GMA
1
Объедините этот ответ с деталями ответа Тэдмана, и вы получите полную картину.
Саргас
5
Авди обновил свое мнение о том, когда использовать и против &&. В основном используйте «и» и «или» для потока управления из-за их более низкого приоритета. devblog.avdi.org/2014/08/26/…
EricC
238

Практическая разница заключается в силе связывания, которая может привести к необычному поведению, если вы не готовы к этому:

foo = :foo
bar = nil

a = foo and bar
# => nil
a
# => :foo

a = foo && bar
# => nil
a
# => nil

a = (foo and bar)
# => nil
a
# => nil

(a = foo) && bar
# => nil
a
# => :foo

То же самое работает для ||и or.

Тадман
источник
2
a = foo and bar и (a = foo ) && bar доказывает, что andимеет более низкий приоритет, чем &&.
Саргас
я не понимаю: что значит "foo and bar" вернуть?
BKSpurgeon
a = foo and barэквивалентно (a = :foo) and nil. Поскольку присваивание возвращает логически истинное значение ( :foo), вторая часть вычисляет, что не удается, и возвращает nil.
tadman
61

Руководство по стилю в Ruby говорит лучше, чем я:

Используйте && / || для логических выражений и / или для потока управления. (Практическое правило. Если вам нужно использовать внешние скобки, вы используете неправильные операторы.)

# boolean expression
if some_condition && some_other_condition
  do_something
end

# control flow
document.saved? or document.save!
Эндрю Гримм
источник
53
На самом деле руководство теперь говорит, чтобы избежать and/ orполностью, и они могут иметь смысл. Часто их использование в потоке управления может быть более явно записано с if/ unlessоператорами (например document.save! unless document.saved?)
Ярин
@akostadinov на случай, если вы не троллите: руководство по Ruby Style не написано создателями Ruby. Ruby был создан Юкихиро Мацумото и другими, в то время как Ruby Style Guide был главным образом Божидар Бацов.
Эндрю Гримм
2
@AndrewGrimm, спасибо, приятно знать. Извините за троллинг, но я искренне путаюсь с некоторыми аспектами рубиновой реальности. Одно можно сказать наверняка - каждый ruby-проект нуждается в строгих политиках стилей, чтобы обеспечить поддержку кода.
Акостадинов
37

||и &&связать с тем приоритетом, который вы ожидаете от логических операторов в языках программирования ( &&очень сильный, ||немного менее сильный).

andи orимеют более низкий приоритет.

Например, в отличие от ||, orимеет более низкий приоритет, чем =:

> a = false || true
 => true 
> a
 => true 
> a = false or true
 => true 
> a
 => false

Аналогично, в отличие &&, andтакже имеет более низкий приоритет, чем =:

> a = true && false
 => false 
> a
 => false 
> a = true and false
 => false 
> a
 => true 

Более того, в отличие от &&и ||, andи orсвязать с равным приоритетом:

> !puts(1) || !puts(2) && !puts(3)
1
 => true
> !puts(1) or !puts(2) and !puts(3)
1
3
 => true 
> !puts(1) or (!puts(2) and !puts(3))
1
 => true

Слабое связывание andи orможет быть полезно для целей управления потоком: см. Http://devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby/ .

Гейб Копли
источник
2
"в отличие от ||, orимеет более низкий приоритет, чем =" ... теперь это имеет больше смысла, спасибо!
Steph Sharp
18

andимеет более низкий приоритет, чем &&.

Но для непритязательного пользователя могут возникнуть проблемы, если он используется вместе с другими операторами, приоритет которых находится между, например, оператором присваивания:

def happy?() true; end
def know_it?() true; end

todo = happy? && know_it? ? "Clap your hands" : "Do Nothing"

todo
# => "Clap your hands"

todo = happy? and know_it? ? "Clap your hands" : "Do Nothing"

todo
# => true
Santhosh
источник
1
Спасибо, но чем приоритет "и" отличается от "&&"?
BKSpurgeon
2
@BKSpurgeon Смотрите здесь упорядоченный список приоритетов операторов в Ruby.
thutt
5

andимеет более низкий приоритет, в основном мы используем его как модификатор потока управления, такой как if:

next if widget = widgets.pop

становится

widget = widgets.pop and next

Для or:

raise "Not ready!" unless ready_to_rock?

становится

ready_to_rock? or raise "Not ready!"

Я предпочитаю использовать, ifно нет and, потому что ifэто более понятно, поэтому я просто игнорирую andи or.

Обратитесь к разделу « Использование« и »и« или »в Ruby » для получения дополнительной информации.

Feuda
источник
0

Я не знаю, является ли это намерением Ruby или это ошибка, но попробуйте этот код ниже. Этот код был запущен в Ruby версии 2.5.1 и в системе Linux.

puts 1 > -1 and 257 < 256
# => false

puts 1 > -1 && 257 < 256
# => true
Кевин Нг
источник
1
@JakubArnold Сарказм никогда не помогает. Примеры иногда есть.
BobRodes
@BobRodes Это был не сарказм. Есть 7 ответов, 6 из которых уже есть примеры.
Якуб Арнольд
1
@JakubArnold Я все еще нашел этот пример полезным.
BobRodes
Я тоже получаю странные результаты. v1 = true и false p v1 # => app.rb: true, IRB: false v2 = true && false p v2 # => app.rb: false, IRB: false устанавливает 1> -1 && 257 <256 # => app.rb: false, IRB: false
Rich_F