V. Opérateurs▲
Certaines personnes appellent Perl un « langage orienté opérateur ». Pour comprendre un programme Perl, vous devez comprendre comment les opérateurs interagissent avec leurs opérandes.
Un opérateur Perl est une série d'un ou plusieurs symboles utilisés dans le cadre de la syntaxe du langage. Chaque opérateur fonctionne sur zéro, un ou plusieurs opérandes. Considérez un opérateur comme une sorte particulière de fonction comprise par l'analyseur et ses opérandes comme des arguments.
V-A. Caractéristiques des opérateurs▲
Chaque opérateur possède plusieurs caractéristiques importantes qui régissent son comportement : le nombre d'opérandes sur lesquels il opère, les relations avec les autres opérateurs, les contextes qu'il applique et la syntaxe qu'il fournit.
perldoc perlop et perldoc perlsyn fournissent un grand volume d'informations sur les opérateurs Perl, mais la documentation suppose que vous connaissez déjà assez bien quelques concepts informatiques essentiels. Ces idées semblent compliquées, mais elles utilisent des noms complexes pour des concepts que vous connaissez déjà, même si vous n'y avez jamais réfléchi. Si vous pouvez faire des mathématiques élémentaires dans votre tête, tout ira bien.
V-A-1. Ordre des opérations (priorité)▲
La priorité (ou précédence) d'un opérateur établit quand Perl doit l'évaluer dans une expression. L'ordre d'évaluation procède de la priorité la plus élevée vers la plus basse. Vous rappelez-vous les mathématiques de base ? Multiplier et diviser avant d'additionner ou soustraire. C'est la priorité. Parce que la priorité de la multiplication est supérieure à la priorité de l'addition, en Perl 7 + 7 * 10 est évalué à 77 et pas à 140.
Pour forcer l'évaluation de certains opérateurs avant les autres, groupez leurs sous-expressions entre parenthèses. En (7 + 7) * 10, le regroupement de l'addition en une seule unité oblige son évaluation avant la multiplication. Le résultat est 140.
perldoc perlop contient un tableau de priorités. Parcourez-le quelques fois, mais ne vous donnez pas la peine de le mémoriser (presque personne ne le fait). Passez votre temps à simplifier votre code où vous le pouvez et ajoutez des parenthèses pour clarification où vous en avez besoin.
Dans les cas où deux opérateurs ont la même priorité, d'autres facteurs tels que l'associativité (AssociativitéAssociativité) et la fixité (FixitéFixité) permettent de départager.
V-A-2. Associativité▲
L'associativité d'un opérateur détermine s'il est évalué de gauche à droite ou de droite à gauche. L'addition est associative à gauche, de sorte que 2 + 3 + 4 évalue d'abord 2 + 3, puis ajoute 4 au résultat. L'exponentiation est associative à droite, de sorte que 2 ** 3 ** 4 évalue d'abord 3 ** 4, puis élève 2 à la puissance 81. Comme d'habitude, le regroupement entre parenthèses vous permet de changer l'ordre d'évaluation.
Si vous mémorisez uniquement la priorité et l'associativité des opérateurs mathématiques courants, cela suffira. Simplifiez votre code et vous n'aurez pas à mémoriser d'autres associativités.
Le module standard B::Deparse est un outil de débogage inestimable. Exécutez perl -MO=Deparse,-p sur un bout de code pour voir exactement comment Perl gère la priorité et l'associativité des opérateurs. L'option -p ajoute des parenthèses de regroupement supplémentaires qui précisent souvent l'ordre d'évaluation.
Méfiez-vous, car l'optimiseur de Perl simplifiera les opérations mathématiques qui utilisent des valeurs constantes. Pour contourner ce problème, utilisez à la place des variables nommées, comme dans $x ** $y ** $z.
V-A-3. Arité▲
L'arité d'un opérateur est le nombre d'opérandes sur lesquels il opère. Un opérateur d'arité 0 opère sur zéro opérande. Un opérateur unaire opère sur un opérande. Un opérateur binaire opère sur deux opérandes. Un opérateur ternaire opère sur trois opérandes. Un opérateur de liste opère sur une liste d'opérandes.
Les opérateurs arithmétiques sont des opérateurs binaires et sont généralement associatifs à gauche. 2 + 3 - 4 évalue d'abord 2 + 3 ; l'addition et la soustraction ont la même priorité, mais elles sont associatives à gauche et binaires, donc l'ordre approprié d'évaluation applique l'opérateur le plus à gauche (+) aux deux opérandes le plus à gauche (2 et 3) avec l'opérateur le plus à gauche (+), puis applique l'opérateur le plus à droite (-) au résultat de la première opération et à l'opérande le plus à droite (4).
Les débutants en Perl confondent souvent l'interaction des opérateurs de listes surtout les appels de fonctions et les expressions imbriquées. Là où généralement les parenthèses aident, méfiez-vous de la complexité de l'analyse de ce code :
# code probablement bogué
say
( 1
+
2
+
3
) *
4
;
... qui affiche la valeur 6 et est évalué (probablement) dans son ensemble à 4 (la valeur de retour de say multipliée par 4). L'analyseur Perl interprète les parenthèses comme des opérateurs postcirconfixés (FixitéFixité) désignant les arguments de say, pas comme des parenthèses circonfixées regroupant une expression pour modifier la priorité.
V-A-4. Fixité▲
La fixité (ne mémorisez pas tous ces mots, retenez juste leur signification) d'un opérateur est sa position par rapport à ses opérandes :
- les opérateurs infixés apparaissent entre leurs opérandes. La plupart des opérateurs mathématiques sont des opérateurs infixés, comme l'opérateur de multiplication dans $longueur * $largeur ;
- les opérateurs préfixés précèdent leurs opérandes. Les opérateurs postfixés suivent leurs opérandes. Ces opérateurs ont tendance à être unaires, comme la négation mathématique (-$x), la négation booléenne (!$y) et l'incrémentation postfixée ($z++) ;
- Les opérateurs circonfixés entourent leurs opérandes, comme dans le cas du constructeur de hachage anonyme ({...}) et les opérateurs de citation (qq[...]) ;
- les opérateurs postcirconfixés suivent certains opérandes et en entourent d'autres, comme on le voit dans l'accès des éléments de hachages et tableaux ($hachage{$x} et $tableau[$y]).
V-B. Types d'opérateurs▲
Les opérateurs Perl fournissent à leurs opérandes des contextes de valeur (Contextes numériques, de chaîne et booléenContextes numériques, de chaîne et booléen). Pour choisir l'opérateur approprié, vous devez connaître le type des opérandes que vous fournissez ainsi que le type de résultat que vous vous attendez à recevoir.
V-B-1. Opérateurs numériques▲
Les opérateurs numériques imposent des contextes numériques sur leurs opérandes. Ces opérateurs sont les opérateurs arithmétiques standard tels que l'addition (+), la soustraction (-), la multiplication (*), la division (/), l'exponentiation (**), le modulo (%), leurs variantes avec affectation (+=, -=, *=, /=, **= et %=) et les autodécrémentations postfixées et préfixées (--).
L'opérateur d'auto-incrémentation a un comportement spécial avec les chaînes de caractères (Opérateurs spéciauxOpérateurs spéciaux).
Plusieurs opérateurs de comparaison imposent des contextes numériques sur leurs opérandes. Ce sont l'égalité numérique (==), l'inégalité numérique (!=), supérieur à (>), inférieur à (<), supérieur ou égal à (>=), inférieur ou égal à (<=), et l'opérateur de comparaison de tri (<=>).
V-B-2. Opérateurs de chaîne de caractères▲
Les opérateurs de chaînes imposent des contextes de chaîne sur leurs opérandes. Ces opérateurs sont les opérateurs d'application (positive ou négative) d'expressions régulières (=~ et !~) et la concaténation (.).
Plusieurs opérateurs de comparaison imposent des contextes de chaîne sur leurs opérandes. Ce sont l'égalité des chaînes (eq), l'inégalité des chaînes (ne), supérieur à (gt), inférieur à (lt), supérieur ou égal à (ge), inférieur ou égal à (le) et l'opérateur de comparaison de tri de chaîne (cmp).
V-B-3. Opérateurs logiques▲
L'opérateur ou-défini, //, teste si son opérande est défini. Contrairement à || qui teste si son opérande est vrai, // retourne une valeur vraie même si son opérande est évalué à un zéro numérique ou à une chaîne vide. Ceci est particulièrement utile pour attribuer des valeurs par défaut aux paramètres :
L'opérateur conditionnel ternaire (?:) accepte trois opérandes. Il évalue le premier en contexte booléen et retourne le deuxième si le premier est vrai et le troisième sinon :
my $etat_vrai
=
$valeur
?
'true'
: 'false'
;
Les opérateurs préfixés ! et not retournent les contraires logiques des valeurs booléennes de leurs opérandes. not est une version moins prioritaire de !.
L'opérateur xor est un opérateur infixé qui évalue ses opérandes à ou-exclusif.
V-B-4. Opérateurs de bit▲
Les opérateurs de bit traitent leurs opérandes numériquement bit par bit. Ces opérations sont rares. Elles sont le décalage à gauche (<<), le décalage à droite (>>), et binaire (&), ou binaire (|) et xor binaire (^), ainsi que leur variante avec affectation (<<=, >>=, &=, |= et ^=).
V-B-5. Opérateurs spéciaux▲
L'opérateur d'auto-incrémentation a un comportement spécial. Lorsqu'il est utilisé sur une valeur avec une composante numérique (Coercition de variables mises en cacheCoercition de variables mises en cache), l'opérateur incrémente cette composante numérique. Si la valeur est évidemment une chaîne (et n'a aucune composante numérique), l'opérateur incrémente la valeur littérale de l'élément de sorte que a devient b, zz devient aaa, et a9 devient b0.
my $num
=
1
;
my $str
=
'a'
;
$num
++
;
$str
++
;
is( $num
, 2
, 'auto-incrémentation numérique'
);
is( $str
, 'b'
, 'auto-incrémentation de chaîne'
);
no warnings 'numeric'
;
$num
+=
$str
;$str
++
;
is( $num
, 2
, 'addition numérique avec $str'
);
is( $str
, 1
, '... donne à $str une partie numérique'
);
L'opérateur de répétition (x) est un opérateur infixé avec un comportement complexe. Lors de l'évaluation dans un contexte de liste avec une liste comme premier opérande, il renvoie cette liste répétée le nombre de fois spécifié par son second opérande. Lors de l'évaluation dans un contexte de liste avec un scalaire comme premier opérande, il produit une chaîne constituée par la valeur littérale de son premier opérande concaténée à elle-même le nombre de fois spécifié par son second opérande.
En contexte scalaire, l'opérateur répète et concatène une chaîne :
my @sheherazade
=
('nuits'
) x
1001
;
my $calendrier
=
'nuits'
x
1001
;
my $cal_longueur
=
length
$calendar
;
is( @sheherazade
, 1001
, 'liste répétée'
);
is( $cal_longueur
, 1001
*
length
'nuits'
,
'chaîne répétant le mot'
);
my @shenoliste
=
'nuits'
x
1001
;
my $calscalaire
=
('nuits'
) x
1001
;
is( @shenoliste
, 1
, 'liste à un élément répétant le mot'
);
is( length
$calscalaire
,
1001
*
length
'nuits'
, 'encore une chaîne répétant le mot'
);
L'opérateur infixé d'intervalle (..) crée une liste d'éléments dans un contexte de liste :
my @cartes
=
( 2
.. 10
, 'V'
, 'D'
, 'R'
, 'A'
);
Il peut créer seulement des successions simples auto-incrémentées d'entiers ou de chaînes.
Dans un contexte booléen, l'opérateur d'intervalle devient l'opérateur flip-flop. Cet opérateur produit une valeur fausse jusqu'à ce que son opérande gauche soit vrai. Cette valeur reste vraie jusqu'à ce que l'opérande droit soit vrai, après quoi la valeur est à nouveau fausse jusqu'à ce que l'opérande gauche soit à nouveau vrai. Imaginez l'analyse du texte d'une lettre officielle :
while (/Bonjour,
$user
/
.. /Cordialement,/
)
{
say
">
$_
"
;
}
L'opérateur virgule (,) est un opérateur infixé. Dans un contexte scalaire, il évalue son opérande gauche puis retourne la valeur produite par l'évaluation de son opérande droit. Dans un contexte de liste, il évalue les deux opérandes de gauche à droite.
L'opérateur grosse virgule (=>) fait la même chose que la virgule et met aussi automatiquement entre guillemets tout « mot nu » utilisé comme opérande gauche (Tables de hachageTables de hachage).
L'opérateur triple point se substitue à une instruction simple. Il est d'arité 0 et n'a ni priorité, ni associativité. Il est passé correctement à la compilation, mais lève une exception avec la chaîne Unimplemented s'il est exécuté. Cela en fait un excellent emplacement dans du code dont vous pensez qu'il ne sera jamais exécuté :
sub un_exemple {
# implémentez vous-même ceci
...
}