Ternary conditional operator

From Wikipedia, the free encyclopedia
Jump to navigation Jump to search

Template:Short description Template:Redirect Template:Redirect

In computer programming, the ternary conditional operator is a ternary operator that evaluates to one of two values based on a Boolean expression. The operator is also known as conditional operator, ternary if, immediate if, or inline if (iif). Although many ternary operators are theoretically possible, the conditional operator is commonly used and other ternary operators rare, so the conditional variant is commonly referred to as the ternary operator.

Typical syntax for an expression using the operator is like <syntaxhighlight lang="text" class="" style="" inline="1">if a then b else c</syntaxhighlight> or <syntaxhighlight lang="text" class="" style="" inline="1">a ? b : c</syntaxhighlight>. One can read it aloud as "if a then b otherwise c". The form <syntaxhighlight lang="text" class="" style="" inline="1">a ? b : c</syntaxhighlight> is the most common, but alternative syntax exists. For example, Raku uses the syntax <syntaxhighlight lang="text" class="" style="" inline="1">a ?? b !! c</syntaxhighlight> to avoid confusion with the infix operators <syntaxhighlight lang="text" class="" style="" inline="1">?</syntaxhighlight> and <syntaxhighlight lang="text" class="" style="" inline="1">!</syntaxhighlight>, whereas in Visual Basic, it takes the form <syntaxhighlight lang="text" class="" style="" inline="1">If(a, b, c)</syntaxhighlight>.

The construct first appeared in CPL, in which equivalent syntax for <syntaxhighlight lang="text" class="" style="" inline="1"> a ? b : c</syntaxhighlight> is a → b, c.<ref>Template:Cite journal</ref><ref>Template:Cite book</ref>

Patterns

Assignment

The value of the operator can be assigned to a variable. For a weakly typed language, the data type of the selected value may determine the type of the assigned value. For a strongly typed language, both value expressions must evaluate to a type that is compatible with the target variable.

The operator is similar to the way conditional expressions (if-then-else) work in functional programming languages, like Scheme, ML, Haskell, and XQuery, since if-then-else forms an expression instead of a statement in those languages.

The operator allows for initializing a variable via a single statement which otherwise might require multiple statements. Use in variable assignment reduces the probability of a bug from a faulty assignment as the assigned variable is stated only once.

For example, in Python:

<syntaxhighlight lang="python"> x: str = 'foo' if b else 'bar' </syntaxhighlight>

instead of:

<syntaxhighlight lang="python"> x: str if b:

   x = 'foo'

else:

   x = 'bar'

</syntaxhighlight>

In a language with block scope, a variable must be declared before the if-else statement. For example:

<syntaxhighlight lang="cpp"> std::string s; if (b) {

   s = "foo";

} else {

   s = "bar";

} </syntaxhighlight>

Use of the conditional operator simplifies this:

<syntaxhighlight lang="cpp"> std::string s = b ? "foo" : "bar"; </syntaxhighlight>

Furthermore, since initialization is now part of the declaration, rather than a separate statement, the identifier can be a constant. For example:

<syntaxhighlight lang="cpp"> const std::string s = b ? "foo" : "bar"; </syntaxhighlight>

Case selector

The conditional operator can be used for case selectors. For example:

<syntaxhighlight lang="c"> vehicle = arg == 'B' ? bus :

         arg == 'A' ? airplane :
         arg == 'T' ? train :
         arg == 'C' ? car :
         arg == 'H' ? horse :
                      feet;

</syntaxhighlight>

Variations

The syntax and semantics of the operator vary by language.

Major differences include whether the expressions can have side effects and whether the language provides short-circuit evaluation semantics, whereby only the selected expression is evaluated.

If a language supports expressions with side effects but does not specify short-circuit evaluation, then a further distinction exists about which expression evaluates first. If no order is guaranteed, a distinction exists about whether the result is then classified as indeterminate (the value obtained from some order) or undefined (any value at all at the whim of the compiler in the face of side effects, or even a crash).

If a language does not permit side-effects in expressions (common in functional languages), then the order of evaluation has no value semantics Template:En dash though it may yet bear on whether an infinite recursion terminates, or have other performance implications (in a functional language with match expressions, short-circuit evaluation is inherent, and natural uses for the ternary operator arise less often, so this point is of limited concern).

For these reasons, in some languages the statement form <syntaxhighlight lang="text" class="" style="" inline="1">r = condition ? expr1 : expr2</syntaxhighlight> can have subtly different semantics than the block conditional form <syntaxhighlight lang="c" class="" style="" inline="1">if (condition) { r = expr1; } else { r = expr2; }</syntaxhighlight>.

In almost all languages, the ternary operator is right associative, so that <syntaxhighlight lang="text" class="" style="" inline="1">a == 1 ? "one" : a == 2 ? "two" : "many"</syntaxhighlight> evaluates intuitively as <syntaxhighlight lang="text" class="" style="" inline="1">a == 1 ? "one" : (a == 2 ? "two" : "many")</syntaxhighlight>. This means it can be chained similarly to an if ... else if ... else if ... else chain. The main exception is PHP, in which it was left-associative (such that the same expression evaluates to <syntaxhighlight lang="text" class="" style="" inline="1">(a == 1 ? "one" : a == 2) ? "two" : "many"</syntaxhighlight>, which is rarely what the programmer expects)<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref> prior to version 8, and is non-associative thereafter.<ref>https://www.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary</ref>

Furthermore, in all C-family languages and many others, the ternary conditional operator has low operator precedence.

Equivalence to map

The ternary operator can also be viewed as a binary map operation.

In R—and other languages with literal expression tuples—one can simulate the ternary operator with something like the R expression <syntaxhighlight lang="r" class="" style="" inline="1">c(expr1,expr2)[1+condition]</syntaxhighlight> (this idiom is slightly more natural in languages with 0-origin subscripts). Nested ternaries can be simulated as <syntaxhighlight lang="r" class="" style="" inline="1">c(expr1,expr2,expr3)[which.first((c(cond1,cond2,TRUE))]</syntaxhighlight> where the function <syntaxhighlight lang="text" class="" style="" inline="1">which.first</syntaxhighlight> returns the index of the first true value in the condition vector. Note that both of these map equivalents are binary operators, revealing that the ternary operator is ternary in syntax, rather than semantics. These constructions can be regarded as a weak form of currying based on data concatenation rather than function composition.

If the language provides a mechanism of futures or promises, then short-circuit evaluation can sometimes also be simulated in the context of a binary map operation.

Examples

Ada

The 2012 edition of Ada has introduced conditional expressions (using <syntaxhighlight lang="text" class="" style="" inline="1">if</syntaxhighlight> and <syntaxhighlight lang="text" class="" style="" inline="1">case</syntaxhighlight>), as part of an enlarged set of expressions including quantified expressions and expression functions. The Rationale for Ada 2012<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref> states motives for Ada not having had them before, as well as motives for now adding them, such as to support "contracts" (also new).

<syntaxhighlight lang="ada"> Pay_per_Hour := (if Day = Sunday then 12.50 else 10.00); </syntaxhighlight>

When the value of an if_expression is itself of Boolean type, then the <syntaxhighlight lang="text" class="" style="" inline="1">else</syntaxhighlight> part may be omitted, the value being True. Multiple conditions may chained using <syntaxhighlight lang="text" class="" style="" inline="1">elsif</syntaxhighlight>.

ALGOL 60

ALGOL 60 introduced conditional expressions (ternary conditionals) to imperative programming languages.

This conditional statement:

<syntaxhighlight lang="pascal"> integer opening_time; if day = Sunday then

   opening_time := 12;

else

   opening_time := 9;

</syntaxhighlight>

Can be rewritten with the conditional operator::

<syntaxhighlight lang="pascal"> integer opening_time; opening_time := if day = Sunday then 12 else 9; </syntaxhighlight>

ALGOL 68

Both ALGOL 68's choice clauses (if and case clauses) support the following:

Single if choice clause
<syntaxhighlight lang="text" class="" style="" inline="1">if condition then statements [ else statements ] fi</syntaxhighlight> or a brief form: ( condition | statements | statements )
Chained if choice clause
<syntaxhighlight lang="text" class="" style="" inline="1">if condition1 then statements elif condition2 then statements [ else statements ] fi</syntaxhighlight> or a brief form: ( condition1 | statements |: condition2 | statements | statements ).

Bash

A true ternary operator only exists for arithmetic expressions:

<syntaxhighlight lang="bash"> ((result = condition ? value_if_true : value_if_false)) </syntaxhighlight>

For strings there only exist workarounds, like e.g.:

<syntaxhighlight lang="bash"> result=$("$a" = "$b" && echo "value_if_true" || echo "value_if_false") </syntaxhighlight>

Where <syntaxhighlight lang="text" class="" style="" inline="1">"$a" = "$b"</syntaxhighlight> can be any condition <syntaxhighlight lang="text" class="" style="" inline="1"></syntaxhighlight> construct can evaluate. Instead of the <syntaxhighlight lang="text" class="" style="" inline="1"></syntaxhighlight> there can be any other bash command. When it exits with success, the first echo command is executed, otherwise the second one is executed.

C family

The following code in C assigns <syntaxhighlight lang="text" class="" style="" inline="1">result</syntaxhighlight> to the value of x if a > b; otherwise to y. This is the same syntax as in many related languages including C++, Java, JavaScript, and Dart.

<syntaxhighlight lang="c"> result = a > b ? x : y; </syntaxhighlight>

Only the selected expression is evaluated. In this example, x and y require no evaluation, but they can be expressions with side effects. Only the side-effect for the selected expression value will occur.<ref name="ISO/IEC 9899:1999">ISO.IEC 9899:1999 (E) 6.5.15.4</ref><ref name="java">Java 7 Specification: 15.25 Conditional Operator ? : </ref>

If x and y are of the same data type, the conditional expression generally has that type. Otherwise, the rules governing the resulting data type vary a little between languages:

  • In C++, the usual arithmetic type conversions are performed to convert x and y to a common type. If both are pointer or reference types, or one is a pointer type and the other is a constant expression evaluating to 0, pointer or reference conversions are performed to convert them to a common type.<ref>{{#invoke:citation/CS1|citation

|CitationClass=web }}</ref>

  • In C#, if one expression is implicitly convertible to the type of the other, that type is used. Otherwise, a compile-time error occurs.<ref name=":0">{{#invoke:citation/CS1|citation

|CitationClass=web }}</ref>

  • In dynamically typed languages, the evaluated expression has the type of the selected expression.

Furthermore in C++, a conditional expression can be used as an lvalue, if both x and y are lvalues, though this is rarely used in practice:<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref> <syntaxhighlight lang="c++"> (foo ? bar : baz) = frink; </syntaxhighlight>

Common Lisp

Assignment using a conditional expression in Common Lisp:

<syntaxhighlight lang="lisp"> (setq result (if (> a b) x y)) </syntaxhighlight>

Alternative form:

<syntaxhighlight lang="lisp"> (if (> a b)

 (setq result x)
 (setq result y))

</syntaxhighlight>

dBASE

In dBase, the conditional function iif(<expL>, <expT>, <expF>) is called "Immediate IF". It uses shortcut evaluation (it only evaluates one of Template:Mono or Template:Mono).

For example, to sort a list by the street name and then (in most cases) house number, one could type

Template:Codett to indexfile

at the dBASE III command prompt, and then copy or export the table.

Fortran

As part of the Fortran-90 Standard, the ternary operator was added to Fortran as the intrinsic function <syntaxhighlight lang="text" class="" style="" inline="1">merge</syntaxhighlight>:

<syntaxhighlight lang="fortran"> variable = merge(x,y,a>b) </syntaxhighlight>

Note that both x and y are evaluated before the results of one or the other are returned from the function. Here, x is returned if the condition holds true and y otherwise.

Fortran-2023 added conditional expressions which evaluate one or the other of the expressions based on the conditional expression:

<syntaxhighlight lang="fortran"> variable = ( a > b ? x : y ) </syntaxhighlight>

Kotlin

Kotlin does not include the traditional <syntaxhighlight lang="text" class="" style="" inline="1">?:</syntaxhighlight> ternary operator, however, an <syntaxhighlight lang="text" class="" style="" inline="1">if</syntaxhighlight> can be used as an expression that can be assigned,<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref> achieving the same results.

<syntaxhighlight lang="kotlin"> val max = if (a > b) a else b </syntaxhighlight>

Lua

Lua does not have a traditional conditional operator. However, the short-circuiting behavior of its <syntaxhighlight lang="text" class="" style="" inline="1">and</syntaxhighlight> and <syntaxhighlight lang="text" class="" style="" inline="1">or</syntaxhighlight> operators allows the emulation of this behaviour. The following is equivalent to: var = cond ? a : b.

<syntaxhighlight lang="lua"> var = cond and a or b </syntaxhighlight>

This will succeed unless <syntaxhighlight lang="text" class="" style="" inline="1">a</syntaxhighlight> is logically false; in this case, the expression will always result in <syntaxhighlight lang="text" class="" style="" inline="1">b</syntaxhighlight>. This can result in some surprising behavior if ignored.

There are also other variants that can be used, but they're generally more verbose:

<syntaxhighlight lang="lua"> var = (

 {
   [true] = a,
   [false] = b
 }

)[not not cond] </syntaxhighlight>

Luau, a dialect of Lua, has ternary expressions that look like if statements, but unlike them, they have no <syntaxhighlight lang="luau" class="" style="" inline="1">end</syntaxhighlight> keyword, and the <syntaxhighlight lang="luau" class="" style="" inline="1">else</syntaxhighlight> clause is required. One may optionally add <syntaxhighlight lang="luau" class="" style="" inline="1">elseif</syntaxhighlight> clauses. It's designed to replace the <syntaxhighlight lang="lua" class="" style="" inline="1">cond and a or b</syntaxhighlight> idiom and is expected to work properly in all cases.<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref>

<syntaxhighlight lang="luau"> -- in Luau var = if cond then a else b

-- with elseif clause sign = if var < 0 then -1 elseif var == 0 then 0 else 1 </syntaxhighlight>

Pascal

Pascal was both a simplification and extension of ALGOL 60 (mainly for handling user-defined types). One simplification was to remove the conditional expression since the same could be achieved with the less succinct conditional statement form.

RemObjects Oxygene added a ternary operator to Object Pascal in approximately 2011,<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref> and in 2025 Delphi followed suit.<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref> Oxygene supports case/switch statements, essentially a repeated if, as expressions evaluating to a value as well.<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref>

Python

An operator for a conditional expression in Python was approved as Python Enhancement Proposal 308 and was added to the 2.5 release in September 2006. Python's conditional operator differs from the common <syntaxhighlight lang="text" class="" style="" inline="1">?:</syntaxhighlight> operator in the order of its operands. The general form is:<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref>

<syntaxhighlight lang="python"> result = x if a > b else y </syntaxhighlight>

This form invites considering <syntaxhighlight lang="text" class="" style="" inline="1">x</syntaxhighlight> as the normal value and <syntaxhighlight lang="text" class="" style="" inline="1">y</syntaxhighlight> as an exceptional case.

Rust

Being an expression-oriented programming language, Rust's existing if expr1 else expr2 syntax can behave as the traditional <syntaxhighlight lang="text" class="" style="" inline="1">?:</syntaxhighlight> ternary operator does. Earlier versions of the language did have the <syntaxhighlight lang="text" class="" style="" inline="1">?:</syntaxhighlight> operator but it was removed<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref> due to duplication with <syntaxhighlight lang="text" class="" style="" inline="1">if</syntaxhighlight>.<ref>{{#invoke:citation/CS1|citation |CitationClass=web }}</ref>

Note the lack of semi-colons in the code below compared to a more declarative <syntaxhighlight lang="text" class="" style="" inline="1">if</syntaxhighlight>...<syntaxhighlight lang="text" class="" style="" inline="1">else</syntaxhighlight> block, and the semi-colon at the end of the assignment to <syntaxhighlight lang="text" class="" style="" inline="1">y</syntaxhighlight>.

<syntaxhighlight lang="rust"> let x = 5;

let y = if x == 5 {

   10

} else {

   15

}; </syntaxhighlight>

This could also be written as:

<syntaxhighlight lang="rust"> let y = if x == 5 { 10 } else { 15 }; </syntaxhighlight>

Note that curly braces are mandatory in Rust conditional expressions.

You could also use a <syntaxhighlight lang="text" class="" style="" inline="1">match</syntaxhighlight> expression:

<syntaxhighlight lang="rust"> let y = match x {

   5 => 10,
   _ => 15,

}; </syntaxhighlight>

Smalltalk

Every expression (message send) has a value. Thus <syntaxhighlight lang="text" class="" style="" inline="1">ifTrue:ifFalse:</syntaxhighlight> can be used:

<syntaxhighlight lang="scheme"> |x y|

x := 5. y := (x == 5) ifTrue:[10] ifFalse:[15]. </syntaxhighlight>

SQL

The SQL <syntaxhighlight lang="text" class="" style="" inline="1">CASE</syntaxhighlight> expression is a generalization of the ternary operator. Instead of one conditional and two results, n conditionals and n+1 results can be specified.

With one conditional it is equivalent (although more verbose) to the ternary operator:

<syntaxhighlight lang="sql"> SELECT (CASE WHEN a > b THEN x ELSE y END) AS CONDITIONAL_EXAMPLE

 FROM tab;

</syntaxhighlight>

This can be expanded to several conditionals:

<syntaxhighlight lang="sql"> SELECT (CASE WHEN a > b THEN x WHEN a < b THEN y ELSE z END) AS CONDITIONAL_EXAMPLE

 FROM tab;

</syntaxhighlight>

Visual Basic

Visual Basic provides a ternary conditional function, <syntaxhighlight lang="text" class="" style="" inline="1">IIf</syntaxhighlight>, as shown in the following code:

<syntaxhighlight lang="vbnet"> Dim opening_time As Integer = IIf((day = SUNDAY), 12, 9) </syntaxhighlight>

As a function, the values of the three arguments are evaluated before the function is called. To avoid evaluating the expression that is not selected, the <syntaxhighlight lang="text" class="" style="" inline="1">If</syntaxhighlight> keyword was added (in Visual Basic .Net 9.0) as a true ternary conditional operator. This allows the following code to avoid an exception if it were implemented with <syntaxhighlight lang="text" class="" style="" inline="1">IIf</syntaxhighlight> instead:

<syntaxhighlight lang="vbnet"> Dim name As String = If(person Is Nothing, "", person.Name) </syntaxhighlight>

See also

References

Template:Reflist

de:Bedingte Anweisung und Verzweigung#Auswahloperator