66 votes

Pourquoi l'expression (true == true == true) produit-elle une erreur de syntaxe ?

Rubis :

true == true == true

erreur de syntaxe, tEQ inattendu

vs. JavaScript :

true == true == true
// => true

vs. C :

1 == 1 == 1
// => 1

2 votes

Ce qui est intéressant, c'est que seuls les opérateurs d'égalité ( == , === y != ) qui le font. Même les < y > s'analyse correctement et produit ensuite une erreur d'exécution, comme vous vous y attendez. De plus, le seulement sources Je n'ai trouvé aucune grammaire complète pour Ruby, ce qui semble indiquer que cette syntaxe est autorisée.

2 votes

Il fonctionne également sans parenthèses comme ceci, avec un appel explicite, true .== true .== true

4 votes

Je me demande combien d'autres personnes ont tapé avec incrédulité le code défaillant dans l'irb en s'attendant à un résultat différent.

50voto

potashin Points 37585

La direction de l'association, qui contrôle l'ordre des opérateurs dont les arguments sont évalués, n'est pas définie pour l'élément == comme pour la méthode === , != , =~ y <=> (qui ont toutes la même priorité et forment exclusivement un groupe de priorité distinct).

Documentation

Ainsi, l'ordre d'évaluation dans le cas où plusieurs opérateurs de la liste mentionnée ci-dessus sont enchaînés dans une ligne doit être défini explicitement par l'intermédiaire de

  • parenthèse () :

    (true == true) == true # => true
    true == (true == true) # => true
  • ou opérateur point . ( peut être omis pour le dernier contrôle d'égalité d'une rangée ):

    true .== true == true # => true

1 votes

J'aimerais savoir pourquoi mais je pense que cela dépasse le cadre de la question et de votre réponse.

13 votes

@CarySwoveland peut-être parce que 1 == 1 == 1 serait évaluée à false en Ruby si == était associatif à gauche, ce qui entraînerait probablement plusieurs bogues. Et cela n'aurait pas beaucoup de sens non plus - les seules valeurs raisonnables pour le troisième opérande sont true y false , c'est-à-dire a == b == true y a == b == false qui peut être exprimée comme suit a == b y a != b .

2 votes

@Stefan : il n'y a qu'une seule situation où l'on peut l'utiliser de cette manière et où cela aurait un sens, bien que je doive dire que l'exemple est un peu tiré par les cheveux : == peut être surchargée dans une classe personnalisée et le contrôle d'égalité peut donc renvoyer autre chose qu'un simple true o false (par exemple, nil )

7voto

Arye Eidelman Points 345

TL;DR La syntaxe implique que les 3 valeurs sont égales, ce qui n'est pas le cas en javascript ou en C. En donnant une erreur de syntaxe, Ruby ouvre la porte à une implémentation future.

Si je comprends bien la question value_a == value_b == value_c ne doit renvoyer true que si elles sont toutes égales en utilisant == comme opérateur de comparaison, comme le montre cette méthode

# version 1
def compare_3_values(a, b, c)
  a == b && a == c && b == c
end

Il y a cependant un autre résultat attendu possible. pour le mettre en œuvre comme indiqué dans la réponse précédente :

#version 2
def compare_3_values(a, b, c)
  (a == b) == c
end

Les résultats sont très différents.

JavaScript utilise toujours la version 2, ce qui est assez inutile car le troisième élément est toujours comparé à true ou false (0 ou 1 si le troisième élément est un entier), c'est pourquoi false == false == true retourne à la réalité.

La bonne nouvelle, c'est que ruby donne une erreur de syntaxe et que c'est le seul langage qui peut implémenter cela sans casser le code de tout le monde.

pour tout autre langage, cela casserait tellement de code que même si cela était implémenté dans une version majeure ultérieure, il faudrait un drapeau/paramètre pour l'activer ou le désactiver pendant des années, ce qui n'en vaudrait jamais la peine.

Quelques résultats intéressants en Ruby

false .== false == true
=> true

false .== true == false
=> true

true .== false == false
=> true

false .== false == false
=> false

true .== true == false
false

Et en javascript

false == false == true
=> true

false == true == false
=> true

true == false == false
=> true

false == false == false
=> false

true == true == false
=> false

Editer testé en C également, agit de manière similaire à JavaScript en comparant le résultat des deux premières valeurs à la troisième valeur.

4voto

Mayo Points 73

En première réponse est excellente, mais au cas où elle ne serait pas tout à fait claire (et où les gens se demanderaient pourquoi), voici quelques exemples supplémentaires.


En C, le == est associatif de gauche à droite et les booléens sont représentés par 1 (vrai) et 0 (faux). 1 == 1 s'évalue à 1 (vrai) et vous évaluez le résultat de la première expression avec la seconde. Vous pouvez essayer :

2 == 2 == 2 // => 0

Ce qui, en C, est évalué comme suit :

(2 == 2) == 2
1 == 2 // => 0

En Javascript, comme en C, == est associatif de gauche à droite. Essayons avec 0 cette fois-ci (bien que le même exemple de C fonctionnerait également) :

0 == 0 == 0
false

Encore une fois :

0 == 0 == 0
true == 0 // => false

En rubis == n'a pas de propriétés associatives, c'est-à-dire qu'il ne peut pas être utilisé plusieurs fois dans une même expression, de sorte que cette expression ne peut pas être évaluée. La raison pour laquelle cette décision a été prise est une question pour l'auteur du langage. De plus, Ruby ne définit pas le chiffre 1 comme un booléen, donc 1 == true est évaluée à false.

En deuxième réponse indique qu'il existe des cas "bizarres" en Ruby, mais qu'ils sont tous évalués comme prévu :

(1 == 1) == 1
true == 1 # => false

1 == (1 == 1)
1 == true # => false

1 .== 1 == 1
(1 == 1) == 1
true == 1 # => false

false .== false == true
(false == false) == true
true == true # => true

false .== true == false
(false == true) == false
false == false # => true

true .== false == false
(true == false) == false
false == false # => true

false .== false == false
(false == false) == false
true == false # => false

true .== true == false
(true == true) == false
true == false # => false

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X