Opérateur conditionnel ternaire
From Wikipedia, the free encyclopedia
En programmation informatique, l'opérateur conditionnel ternaire est un opérateur ternaire qui renvoie l'une de deux valeurs en fonction d'une expression booléenne. Cet opérateur est également connu sous les noms d'opérateur conditionnel, si ternaire, si immédiat ou si en ligne (iif). Bien que de nombreux opérateurs ternaires soient théoriquement possibles, l'opérateur conditionnel est couramment utilisé et les autres opérateurs ternaires sont rares ; c'est pourquoi la variante conditionnelle est généralement désignée comme « l'opérateur ternaire ».
La syntaxe type d'une expression utilisant l'opérateur est la suivante : si a alors b sinon c ou a ? b : c. On peut le lire à haute voix ainsi : « si a, alors b ; sinon c ». La forme a ? b : c est la plus courante, mais il existe d'autres syntaxes. Par exemple, Raku utilise la syntaxe a ?? b !! c pour éviter toute confusion avec les opérateurs infixes ? et !, alors qu'en Visual Basic, cela prend la forme Iif(a, b, c).
Cette construction apparaît pour la première fois dans CPL, où une syntaxe équivalente pour a ? b : c est a → b, c[1],[2].
Tâche
La valeur de l'opérateur peut être assignée à une variable. Dans un langage à typage faible, le type de données de la valeur sélectionnée peut déterminer le type de la valeur assignée. Dans un langage à typage fort, les deux expressions de valeur doivent donner lieu à un type compatible avec la variable cible.
Cet opérateur fonctionne de manière similaire aux expressions conditionnelles (if-then-else) dans les langages de programmation fonctionnelle, tels que Scheme, ML, Haskell et XQuery, car dans ces langages, la structure if-then-else constitue une expression et non une instruction.
L'opérateur permet d'initialiser une variable à l'aide d'une seule instruction, alors qu'il faudrait autrement plusieurs instructions. Son utilisation lors de l'affectation d'une variable réduit le risque de bogue lié à une affectation erronée, car la variable affectée n'est déclarée qu'une seule fois.
Par exemple, en Python :
x: str = 'foo' if b else 'bar'
au lieu de :
x: str
if b:
x = 'foo'
else:
x = 'bar'
Dans un langage à portée de bloc, une variable doit être déclarée avant l'instruction if-else. Par exemple :
std::string s;
if (b) {
s = "foo";
} else {
s = "bar";
}
L'utilisation de l'opérateur conditionnel simplifie cela :
std::string s = b ? "foo" : "bar";
De plus, comme l'initialisation fait désormais partie de la déclaration, et non plus d'une instruction distincte, l'identificateur peut être une constante. Par exemple :
const std::string s = b ? "foo" : "bar";
Sélecteur de cas
L'opérateur conditionnel peut être utilisé pour les sélecteurs de cas. Par exemple :
véhicule = arg == 'B' ? bus :
arg == 'A' ? avion :
arg == 'T' ? train :
arg == 'C' ? car :
arg == 'H' ? cheval :
pied ;
Variations
La syntaxe et la sémantique de l'opérateur varient selon le langage.
Parmi les principales différences, on peut citer la possibilité pour les expressions d'avoir des effets de bord et la présence ou non, dans le langage, d'une sémantique d'évaluation par court-circuit (de), selon laquelle seule l'expression sélectionnée est évaluée.
Si un langage prend en charge les expressions ayant des effets de bord mais ne spécifie pas d'évaluation par court-circuit, il existe alors une distinction supplémentaire quant à l'expression qui est évaluée en premier. Si aucun ordre n'est garanti, il faut déterminer si le résultat est alors considéré comme indéterminé (la valeur obtenue selon « un certain » ordre) ou indéfini (n'importe quelle valeur choisie au gré du compilateur face aux effets de bord, voire un plantage).
Si un langage n'autorise pas les effets de bord dans les expressions (ce qui est courant dans les langages fonctionnels), l'ordre d'évaluation n'a alors aucune incidence sémantique — même s'il peut néanmoins déterminer si une récursion infinie s'achève ou avoir d'autres implications en termes de performances (dans un langage fonctionnel utilisant des expressions de correspondance, l'évaluation en court-circuit est inhérente, et les utilisations naturelles de l'opérateur ternaire sont moins fréquentes ; ce point n'est donc pas très préoccupant).
C'est pourquoi, dans certaines langues, la forme de l'énoncé r = condition ? expr1 : expr2 peut avoir une sémantique légèrement différente de celle de la forme conditionnelle en bloc if (condition) { r = expr1; } else { r = expr2; }.
Dans presque toutes les langues de programmation, l'opérateur ternaire est associatif (en) à droite, de sorte que a == 1 ? "one" : a == 2 ? "two" : "many" se lit intuitivement comme a == 1 ? "one" : (a == 2 ? "two" : "many"). Cela signifie qu'il peut être enchaîné de la même manière qu'une chaîne if ... else if ... else if ... else. La principale exception est PHP, où l'association se fait par la gauche (de sorte que la même expression donne (a == 1 ? "one" : a == 2) ? "two" : "many", ce qui correspond rarement à ce à quoi s'attend le programmeur)[3] avant la version 8, et est non associative par la suite[4].
De plus, dans tous les langages de la famille C et dans bien d'autres, l'opérateur conditionnel ternaire a une faible priorité.
Équivalence binaire
L'opérateur ternaire peut également être considéré comme une opération de correspondance binaire.
En R — et dans d'autres langages prenant en charge les tuples d'expressions littérales, on peut simuler l'opérateur ternaire à l'aide d'une expression R du type c(expr1,expr2)[1+condition] (cette expression est légèrement plus naturelle dans les langages utilisant des indices à base 0).
Les expressions ternaires imbriquées peuvent être simulées comme suit : c(expr1,expr2,expr3)[which.first((c(cond1,cond2,TRUE))] où la fonction which.first renvoie l'index de la première valeur vraie dans le vecteur de conditions. Il convient de noter que ces deux équivalents de la fonction map sont des opérateurs binaires, ce qui montre que l'opérateur ternaire est ternaire sur le plan syntaxique, et non sémantique. Ces constructions peuvent être considérées comme une forme atténuée de curryfication reposant sur la concaténation de données plutôt que sur la composition de fonctions.
Si le langage propose un mécanisme de futures ou de promesses, l'évaluation par court-circuit peut parfois être simulée dans le cadre d'une opération de mappage binaire.