Ruby et opérateurs : qui a la priorité ?
Il y a un petit piège dans Ruby avec les opérateurs booléens utilisés conjointement avec une affectation. Le côté très intuitif du langage fini pas nous faire oublier quelques règles simples…
Dans une expression booléenne nil est considéré de la même manière que false. Ce qui amène quelquefois à utiliser une syntaxe du type :
machin or truc
Au lieu de (parmis d’autres solutions) :
if machin.nil? # utiliser truc else # utiliser machin end
Mais… il y a un piège. L’expression suivante ne se comporte absolument pas comme on pourrait le supposer :
toto = machin or truc # ca sent le bug ici
En fait l’opérateur d’affectation = a une priorité suppérieure à celle de l’opérateur or. Pour s’en convaincre il suffit de faire le test suivant avec l’interpréteur irb :
irb(main):001:0> toto = false or true => true irb(main):002:0> toto => false
L’expression saisie est évaluée de la manière suivante : (toto = false) or true. Donc l’expression vaut bien true, mais la variable toto se voit affecté la valeur false.
Il y a deux solutions : soit utiliser des parenthèses, soit utiliser l’opérateur || qui a une priorité supérieure à celle de l’affectation :
# deux solutions correctes toto = (machin or truc) toto = machin || truc
Ca a l’air tout bête, une boulette de débutant allez-vous me dire… mais lorsque l’on ne connait pas correctement la priorité des opérateurs, ou que l’on est pas concentré, on fini par avoir quelques bugs par forcément évident à identifier.