Différence entre «et» et && en Ruby?

Réponses:

349

andest identique &&mais avec une priorité inférieure . Ils utilisent tous deux une évaluation de court-circuit .

AVERTISSEMENT: a andmême une priorité inférieure à celle =que vous voudrez généralement éviter and. Un exemple d'utilisation anddoit être trouvé dans le Rails Guide sous " Eviter les erreurs de double rendu ".

Dominic Rodger
la source
50
Ce serait une bonne idée de spécifier que l'on devrait généralement utiliser &&, alors qu'il andne devrait être utilisé que pour des cas très spécifiques.
Marc-André Lafortune
10
Une autre bonne explication ici: devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby .
Andrew Marshall
17
Du lien Andrew Marshall: « Une autre façon de penser andest comme inversé ifmodificateur de déclaration: next if widget = widgets.popdevient widget = widgets.pop and nextVoilà un excellent moyen de le mettre, a vraiment fait. « Click » dans ma tête (Et. orEst comme un inversé unlessmodificateur.)
GMA
1
Combinez cette réponse avec les détails de la réponse de tadman et vous obtenez l'image entière.
sargas
5
Avdi a mis à jour son point de vue sur l'utilisation et sur &&. Fondamentalement, utilisez «et» et «ou» pour le flux de contrôle en raison de leur priorité inférieure. devblog.avdi.org/2014/08/26/…
EricC
238

La différence pratique est la force de liaison, qui peut conduire à un comportement particulier si vous n'y êtes pas préparé:

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

La même chose fonctionne pour ||et or.

tadman
la source
2
a = foo and bar et (a = foo ) && bar prouve que andla priorité est inférieure à &&.
sargas
je ne comprends pas: qu'est-ce que "foo and bar" est censé retourner?
BKSpurgeon
a = foo and barest équivalent à (a = :foo) and nil. Étant donné que l'affectation renvoie une valeur logiquement vraie ( :foo), la deuxième partie est évaluée, ce qui échoue, en retournant nil.
tadman
61

Le Ruby Style Guide le dit mieux que moi:

Utilisez && / || pour les expressions booléennes et / ou pour le flux de contrôle. (Règle générale: si vous devez utiliser des parenthèses externes, vous utilisez les mauvais opérateurs.)

# boolean expression
if some_condition && some_other_condition
  do_something
end

# control flow
document.saved? or document.save!
Andrew Grimm
la source
53
En fait, le guide dit maintenant d'éviter and/ orcomplètement, et ils pourraient avoir un point. Souvent, leur utilisation dans le flux de contrôle peut être plus clairement écrite avec if/ unlessoperators de toute façon (par exemple document.save! unless document.saved?)
Yarin
@akostadinov au cas où vous ne seriez pas à la traîne: le guide Ruby Style n'est pas écrit par les créateurs de Ruby. Ruby a été créé par Yukihiro Matsumoto et d'autres, tandis que le Ruby Style Guide a été principalement par Bozhidar Batsov.
Andrew Grimm
2
@AndrewGrimm, merci, bon à savoir. Désolé pour la pêche à la traîne, mais je suis sincèrement confus avec certains aspects de la réalité rubis. Une chose est sûre - chaque projet Ruby a besoin de politiques de style strictes pour maintenir la base de code maintenable.
akostadinov
37

||et &&lier avec la priorité que vous attendez des opérateurs booléens dans les langages de programmation ( &&est très fort, ||est légèrement moins fort).

andet oront une priorité inférieure.

Par exemple, contrairement à ||, ora une priorité inférieure à =:

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

De même, contrairement à &&, a andégalement une priorité inférieure à =:

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

De plus, contrairement à &&et ||, andet orliez avec la même priorité:

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

Le faiblement contraignant andet orpeut être utile à des fins de contrôle de flux: voir http://devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby/ .

Gabe Kopley
la source
2
"contrairement à ||, ora une priorité inférieure à =" ... maintenant, cela a plus de sens, merci!
Steph Sharp
18

anda une priorité inférieure à &&.

Mais pour un utilisateur modeste, des problèmes peuvent survenir s'il est utilisé avec d'autres opérateurs dont la priorité se situe entre, par exemple, l'opérateur d'affectation:

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
la source
1
Merci, mais en quoi la priorité de "et" est-elle différente de "&&"?
BKSpurgeon
2
@BKSpurgeon Voir ici pour une liste ordonnée de la priorité des opérateurs dans Ruby.
2017
5

anda une priorité plus faible, nous l'utilisons principalement comme modificateur de flux de contrôle tel que if:

next if widget = widgets.pop

devient

widget = widgets.pop and next

Pour or:

raise "Not ready!" unless ready_to_rock?

devient

ready_to_rock? or raise "Not ready!"

Je préfère utiliser ifmais pas and, parce que ifc'est plus intelligible, donc j'ignore juste andet or.

Reportez-vous à " Utilisation de" et "et" ou "dans Ruby " pour plus d'informations.

Feuda
la source
0

Je ne sais pas si c'est l'intention de Ruby ou s'il s'agit d'un bogue, mais essayez ce code ci-dessous. Ce code a été exécuté sur Ruby version 2.5.1 et était sur un système Linux.

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

puts 1 > -1 && 257 < 256
# => true
Kevin Ng
la source
1
@JakubArnold Sarcasm n'est jamais utile. Des exemples le sont parfois.
BobRodes
@BobRodes Ce n'était pas un sarcasme. Il y a 7 réponses, dont 6 ont déjà des exemples.
Jakub Arnold
1
@JakubArnold J'ai toujours trouvé cet exemple utile.
BobRodes
J'obtiens également des résultats étranges. v1 = vrai et faux p v1 # => app.rb: vrai, IRB: faux v2 = vrai && faux p v2 # => app.rb: faux, IRB: faux met 1> -1 && 257 <256 # => app.rb: false, IRB: false
Rich_F