Unterschied zwischen "und" und && in Ruby?

Antworten:

348

andist das gleiche wie &&aber mit niedrigerer Priorität . Beide verwenden eine Kurzschlussauswertung .

WARNUNG: Hat andsogar eine niedrigere Priorität als die =, die Sie normalerweise vermeiden möchten and. Ein Beispiel andfür die Verwendung finden Sie im Rails-Handbuch unter " Vermeiden von Fehlern beim doppelten Rendern ".

Dominic Rodger
quelle
50
Es wäre eine gute Idee anzugeben, dass man normalerweise verwenden sollte &&, während andnur für sehr spezielle Fälle verwendet werden sollte.
Marc-André Lafortune
10
Eine weitere gute Erklärung hier: devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby .
Andrew Marshall
17
Aus Andrew Marshalls Link: "Eine andere Art zu denken andist als ifModifikator für umgekehrte Aussagen: next if widget = widgets.popwird widget = widgets.pop and next. Das ist eine großartige Art, es auszudrücken, hat es wirklich in meinem Kopf" klicken "lassen. (Und orist wie ein unlessModifikator für umgekehrte Aussagen .)
GMA
1
Kombinieren Sie diese Antwort mit den Details von Tadmans Antwort und Sie erhalten das ganze Bild.
Sargas
5
Avdi hat seine Einstellung zum Zeitpunkt der Verwendung und vs. && aktualisiert. Verwenden Sie grundsätzlich 'und' und 'oder' für den Kontrollfluss, da diese eine geringere Priorität haben. devblog.avdi.org/2014/08/26/…
EricC
238

Der praktische Unterschied ist die Bindungsstärke, die zu eigenartigem Verhalten führen kann, wenn Sie nicht darauf vorbereitet sind:

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

Das gleiche funktioniert für ||und or.

Tadman
quelle
2
a = foo and bar und (a = foo ) && bar beweist, dass dies andeine geringere Priorität hat als &&.
Sargas
Ich verstehe es nicht: Was soll "foo and bar" zurückkehren?
BKSpurgeon
a = foo and barist äquivalent zu (a = :foo) and nil. Da die Zuweisung einen logisch wahren Wert ( :foo) zurückgibt, wertet der zweite Teil aus, was fehlschlägt, und gibt zurück nil.
Tadman
61

Der Ruby Style Guide sagt es besser als ich könnte:

Verwenden Sie && / || für boolesche Ausdrücke und / oder für den Kontrollfluss. (Faustregel: Wenn Sie äußere Klammern verwenden müssen, verwenden Sie die falschen Operatoren.)

# boolean expression
if some_condition && some_other_condition
  do_something
end

# control flow
document.saved? or document.save!
Andrew Grimm
quelle
53
Eigentlich sagt der Führer jetzt zu vermeiden and/ orvollständig, und sie könnten einen Punkt haben. Oft könnte ihre Verwendung im Kontrollfluss ohnehin offensichtlicher mit if/ unlessoperator geschrieben werden (zB document.save! unless document.saved?)
Yarin
@akostadinov für den Fall, dass Sie nicht trollten: Der Ruby Style Guide wurde nicht von den Machern von Ruby geschrieben. Ruby wurde von Yukihiro Matsumoto und anderen erstellt, während der Ruby Style Guide hauptsächlich von Bozhidar Batsov verfasst wurde.
Andrew Grimm
2
@ AndrewGrimm, danke, gut zu wissen. Entschuldigung für das Trolling, aber ich bin aufrichtig verwirrt mit einigen Aspekten der rubinroten Realität. Eines ist sicher: Jedes Ruby-Projekt benötigt strenge Stilrichtlinien, um die Codebasis wartbar zu halten.
Akostadinov
37

||und &&binden Sie mit der Priorität, die Sie von booleschen Operatoren in Programmiersprachen erwarten ( &&ist sehr stark, ||ist etwas weniger stark).

andund orhaben eine niedrigere Priorität.

Zum Beispiel, im Gegensatz zu ||, orhat eine geringere Priorität als =:

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

Ebenso im Gegensatz zu &&, andhat auch niedrigere Priorität als =:

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

Was mehr ist , im Gegensatz zu &&und ||, andund orbinden mit gleicher Priorität:

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

Das ist schwach bindend andund orkann für Kontrollflusszwecke nützlich sein: siehe http://devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby/ .

Gabe Kopley
quelle
2
"im Gegensatz zu ||, orhat eine niedrigere Priorität als =" ... jetzt macht es mehr Sinn, danke!
Steph Sharp
18

andhat eine niedrigere Priorität als &&.

Für einen unscheinbaren Benutzer können jedoch Probleme auftreten, wenn er zusammen mit anderen Operatoren verwendet wird, deren Vorrang zwischen dem Zuweisungsoperator liegt, z.

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
quelle
1
Vielen Dank, aber wie unterscheidet sich die Priorität von "und" von "&&"?
BKSpurgeon
2
@BKSpurgeon Hier finden Sie eine geordnete Liste der Operatorprioritäten in Ruby.
Thutt
5

andhat eine niedrigere Priorität, meistens verwenden wir es als Kontrollflussmodifikator wie if:

next if widget = widgets.pop

wird

widget = widgets.pop and next

Für or:

raise "Not ready!" unless ready_to_rock?

wird

ready_to_rock? or raise "Not ready!"

Ich bevorzuge es zu benutzen, ifaber nicht and, weil ifes verständlicher ist, also ignoriere ich einfach andund or.

Weitere Informationen finden Sie unter " Verwenden von" und "und" oder "in Ruby ".

Feuda
quelle
0

Ich weiß nicht, ob dies Ruby-Absicht ist oder ob dies ein Fehler ist, aber versuchen Sie diesen Code unten. Dieser Code wurde auf Ruby Version 2.5.1 ausgeführt und befand sich auf einem Linux-System.

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

puts 1 > -1 && 257 < 256
# => true
Kevin Ng
quelle
1
@ JakubArnold Sarkasmus ist nie hilfreich. Beispiele sind manchmal.
BobRodes
@ BobRodes Es war kein Sarkasmus. Es gibt 7 Antworten, von denen 6 bereits Beispiele haben.
Jakub Arnold
1
@ JakubArnold Ich fand dieses Beispiel immer noch hilfreich.
BobRodes
Ich bekomme auch seltsame Ergebnisse. v1 = wahr und falsch p v1 # => app.rb: wahr, IRB: falsch v2 = wahr && falsch p v2 # => app.rb: falsch, IRB: falsch setzt 1> -1 && 257 <256 # => app.rb: false, IRB: false
Rich_F