Różnica między „i” a && w Ruby?

Odpowiedzi:

349

andjest taki sam, &&ale ma niższy priorytet . Oba używają oceny zwarcia .

OSTRZEŻENIE: andma nawet niższy priorytet niż =zwykle, którego zwykle będziesz chciał uniknąć and. Przykład, kiedy andnależy użyć, można znaleźć w Przewodniku po szynach w sekcji „ Unikanie błędów podwójnego renderowania ”.

Dominic Rodger
źródło
50
Dobrym pomysłem byłoby sprecyzowanie, że zwykle należy go używać &&, a andnależy go używać tylko w bardzo szczególnych przypadkach.
Marc-André Lafortune,
10
Kolejne dobre wyjaśnienie tutaj: devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby .
Andrew Marshall,
17
Z linku Andrew Marshalla: „Innym sposobem myślenia andjest ifmodyfikator odwróconego wyrażenia: next if widget = widgets.popstaje się widget = widgets.pop and next. To świetny sposób na umieszczenie go, naprawdę sprawił, że„ kliknął ”w mojej głowie. (I orjest jak odwrócony unlessmodyfikator.)
GMA
1
Połącz tę odpowiedź ze szczegółami odpowiedzi tadmana, a otrzymasz cały obraz.
sargas
5
Avdi zaktualizował swoje zdanie na temat tego, kiedy stosować oraz vs.&&. Zasadniczo używaj „i” i „lub” do sterowania przepływem ze względu na ich niższy priorytet. devblog.avdi.org/2014/08/26/…
EricC
238

Praktyczną różnicą jest siła wiązania, która może prowadzić do szczególnego zachowania, jeśli nie jesteś na to przygotowany:

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

To samo działa dla ||i or.

tadman
źródło
2
a = foo and bar i (a = foo ) && bar dowodzi, że andma niższy priorytet niż &&.
sargas
nie rozumiem: co oznacza „foo and bar”?
BKSpurgeon
a = foo and barjest równoważne z (a = :foo) and nil. Ponieważ przypisanie zwraca logicznie prawdziwą wartość ( :foo), druga część ocenia, co kończy się niepowodzeniem, powracając nil.
tadman
61

Ruby Style Guide mówi lepiej niż ja:

Użyj && / || dla wyrażeń logicznych i / lub dla przepływu kontrolnego. (Ogólna zasada: jeśli musisz użyć nawiasów zewnętrznych, używasz niewłaściwych operatorów).

# boolean expression
if some_condition && some_other_condition
  do_something
end

# control flow
document.saved? or document.save!
Andrew Grimm
źródło
53
W rzeczywistości przewodnik mówi teraz, aby unikać and/ orcałkowicie, i mogą mieć rację. Często ich użycie w przepływie kontrolnym może być ifiunless tak napisane z / operatorami (np. document.save! unless document.saved?)
Yarin
@akostadinov na wypadek, gdybyś nie trollował: przewodnik po stylu Ruby nie został napisany przez twórców Ruby. Ruby został stworzony przez Yukihiro Matsumoto i innych, podczas gdy Ruby Style Guide został opracowany głównie przez Bozhidara Batsova.
Andrew Grimm,
2
@AndrewGrimm, dzięki, dobrze wiedzieć. Przepraszam za trollowanie, ale szczerze mylę się z niektórymi aspektami rubinowej rzeczywistości. Jedno jest pewne - każdy projekt ruby ​​potrzebuje ścisłych zasad stylu, aby utrzymać bazę kodową w utrzymaniu.
akostadinov
37

||i &&wiążą się z priorytetem, którego oczekujesz od operatorów logicznych w językach programowania ( &&jest bardzo silny, ||jest nieco mniej silny).

andi ormają niższy priorytet.

Na przykład, w przeciwieństwie do ||, orma niższy priorytet niż =:

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

Podobnie, w przeciwieństwie do &&, andma również niższy priorytet niż =:

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

Co więcej, w przeciwieństwie do &&i ||, andi orwiążą się z równym pierwszeństwem:

> !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

Słabo wiążący andi ormoże być przydatny do celów kontroli przepływu: patrz http://devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby/ .

Gabe Kopley
źródło
2
„w przeciwieństwie do ||, orma niższy priorytet niż =”… teraz ma to większy sens, dzięki!
Steph Sharp
18

andma niższy priorytet niż &&.

Ale dla niepozornego użytkownika mogą wystąpić problemy, jeśli zostanie on użyty wraz z innymi operatorami, których pierwszeństwo występuje między, na przykład operator przypisania:

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
źródło
1
Dziękuję, ale czym różni się priorytet „i” od „&&”?
BKSpurgeon
2
@BKSpurgeon Zobacz tutaj, aby uzyskać uporządkowaną listę priorytetów operatorów w Ruby.
thutt 27.07.17
5

andma niższy priorytet, głównie używamy go jako modyfikatora przepływu sterowania, takiego jak if:

next if widget = widgets.pop

staje się

widget = widgets.pop and next

Dla or:

raise "Not ready!" unless ready_to_rock?

staje się

ready_to_rock? or raise "Not ready!"

Wolę używać, ifale nie and, ponieważ ifjest bardziej zrozumiały, więc po prostu ignoruję andi or.

Aby uzyskać więcej informacji, zobacz „ Korzystanie z” i „i” lub w języku Ruby .

Feuda
źródło
0

Nie wiem, czy to jest intencja Ruby, czy to błąd, ale wypróbuj poniższy kod. Ten kod został uruchomiony w Ruby w wersji 2.5.1 i był w systemie Linux.

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

puts 1 > -1 && 257 < 256
# => true
Kevin Ng
źródło
1
@JakubArnold Sarkazm nigdy nie jest pomocny. Przykłady są czasami.
BobRodes
@BobRodes To nie był sarkazm. Istnieje 7 odpowiedzi, z których 6 ma już przykłady.
Jakub Arnold
1
@JakubArnold Nadal uważam ten przykład za pomocny.
BobRodes
Otrzymuję również dziwne wyniki. v1 = true i false p v1 # => app.rb: true, IRB: false v2 = true && false p v2 # => app.rb: false, IRB: false stawia 1> -1 i& 257 <256 # => app.rb: false, IRB: false
Rich_F