Go to Hackademy website

Précédence des opérateurs en ruby et contrôle de flux

Martin Catty

Posté par Martin Catty dans les catégories back

Qu’est ce que la précédence ?

La précédence désigne la priorité et la force des différents opérateurs.

En mathématique les différents opérateurs ont des priorités différentes, par exemple la multiplication prend le pas sur l’addition.

De fait en ruby, comme dans bien d’autres langages, cette expression retourne le résultat attendu :

2 + 3 * 4
=> 14

Pour reprendre la main sur le flux des opérateurs on peut bien sûr utiliser des parenthèses :

(2 + 3) * 4
=> 20

Quels sont les opérateurs ?

Les opérateurs sont les suivants, de la précédence la plus élevée à la plus faible :

[] et []= Accès à un élément du tableau et set d'une valeur
** Exponentiel
! ~ + - Inversion, complément (remplace les bits 0 par 1 et vice-versa), plus et moins (-2 ou +3)
* / % Multiplication, division et modulo
+ - Addition et soustraction
<< >> Décallage de bit vers la droite ou gauche. Retire des bits à droite, ajoute des 0 à gauche. Ex: (9 >> 1).to_s(2)
& AND, opérateur bit à bit, 1 si 1 des deux côtés, 0 sinon. (9 & 14).to_s(2) donne en binaire 1001 & 1110 = 1000 (8)
^ | ^ est l'opérateur bit à bit XOR (ou exclusif). 1 si uniquement un des deux bits est à 1. | est l'opérateur bit à bit OR. 1 si 1 d'un côté au moins.
<= < > >= Opérateurs de comparaison
<=> == === != =~ !~ Comparaison d'égalité ou de matching
&& Et logique. Vrai si les des deux éléments sont évalués à vrai. `true && false` renvoie false.
|| Ou logique. Vrai si l'un des deux éléments est évalué à vrai. `true || false` renvoie true.
.. ... Range incluant et excluant la borne haute : Ex `(1..3).to_a == [1, 2, 3]`. `(1...3).to_a == [1, 2]`
? : Ternaire. Ex: `i % 2 == 0 ? "even" : "odd"`
= += -= &&= etc… Affectations
defined? Vérifie la définition ou non d'une variable
not Négation logique
or and Composition logique
if unless while until Conditions et boucles
begin end Blocs

Contrôle de flux versus opérateurs logiques

La précédence des opérateurs peut avoir des conséquences importantes pour des opérateurs qui semblent avoir le même usage.

C’est le cas de && et and tout comme || et or. Prenons l’exemple suivant :

a = []
b = 1
c = a.empty? and b.is_a?(String)

Le dernier retour sera ici false et c sera true ce qui peut paraître suprenant. On le comprend mieux en prennant en compte la précédence. L’interpréteur ruby va «lire» l’expression de la sorte :

a = []
b = 1
(c = a.empty?) and b.is_a?(String)

En effet l’affectation a une précédence plus forte que le and comme on l’a vu dans le tableau ci dessus.

Avec le && logique le résultat est tout autre et plus proche de ce que l’on attend naturellement :

a = []
b = 1
c = a.empty? && b.is_a?(String)

Le retour est false et c également car l’expression se décompose de la sorte :

a = []
b = 1
c = (a.empty? && b.is_a?(String))

Il en est de même pour les opérateurs or et ||. Il faut en fait voir les opérateurs or et and comme des opérateurs de gestion de flux.

Leur usage est donc plus proche de celui de conditions telles que if, else ou unless que d’un opérateur logique.

Vous avez sans doute déjà vu en Perl ou en PHP des instructions telles que :

chdir '/foo/bar' or die "Can't cd to bar"

Le fonctionnement est le même en ruby et nous permet de gérer le flux de la sorte :

File.exists?('/tmp/bar') or File.new('/tmp/bar', 'w') {}

ce qui est comparable à :

File.new('/tmp/bar', 'w') {} unless File.exists?('/tmp/bar')

La connaissance des opérateurs et de leur précédence est un aspect important du langage. N’hésitez pas à partager vos retours d’expériences et pièges dans lesquels vous avez pu tomber.

L’équipe Synbioz.

Libres d’être ensemble.

Articles connexes

Une brève histoire d'Elixir et Erlang/OTP

31/01/2019

Je développe depuis plusieurs années en Ruby. Depuis mon arrivée chez Synbioz, j’expérimente en plus avec Elixir de façon assez naturelle. En quoi Elixir est-il différent, me demanderez-vous ? Pour...

Écrire une thread pool en Ruby

10/01/2019

Pouvoir exécuter plusieurs tâches en parallèle, que ce soit dans un script ou une application, peut être vraiment très utile, surtout dans le cas où le traitement de ces tâches peut être très long....

Translation temporelle

31/05/2018

Cette semaine, je me suis essayé à un nouveau format d’article qui se présente sous la forme d’une nouvelle de Science-Fiction. Je tiens en passant à remercier Valentin pour ses illustrations....

Authentifier l'accès à vos ressources avec Dragonfly

11/05/2017

Pour ceux qui ne connaissent pas Dragonfly, c’est une application Rack qui peut être utilisée seule ou via un middleware. Le fait que ce soit une application Rack la rend compatible avec toutes les...