Ternary conditional operator: Difference between revisions
(419 intermediate revisions by more than 100 users not shown) | |||
Line 1: | Line 1: | ||
{{Short description|Conditional operator in computer programming}} |
|||
In [[computer programming]], '''<code>?:</code>''' is a [[ternary operator]] that is part of the syntax for a basic [[conditional (programming)|conditional expression]] in several [[programming language]]s. It is commonly referred to as the '''conditional operator''' or '''inline if (iif)'''. |
|||
{{Redirect|?:|use as a binary operator|Elvis operator}} |
|||
In [[computer programming]], the '''ternary conditional operator''' is a [[ternary operator]] that is part of the syntax for basic [[conditional (programming)|conditional expressions]] in several [[programming language]]s. It is commonly referred to as the '''conditional operator''', '''conditional expression''', '''ternary if''', or '''inline if''' (abbreviated '''iif'''). An expression {{code|if a then b else c}} or {{code|a ? b : c}} evaluates to {{code|b}} if the value of {{code|a}} is true, and otherwise to {{code|c}}. One can read it aloud as "if a then b otherwise c". The form {{code|a ? b : c}} is the most common, but alternative syntax do exist; for example, [[Raku (programming language)|Raku]] uses the syntax {{code|a ?? b !! c}} to avoid confusion with the infix operators {{code|?}} and {{code|!}}, whereas in [[Visual Basic .NET]], it instead takes the form {{code|If(a, b, c)}}. |
|||
It originally comes from [[CPL (programming language)|CPL]], in which equivalent syntax for <code>''e''<sub>1</sub> ? ''e''<sub>2</sub> : ''e''<sub>3</sub></code> was <code>''e''<sub>1</sub> → ''e''<sub>2</sub>, ''e''<sub>3</sub></code>.<ref>{{cite journal|first=Christopher|last=Strachey|authorlink=Christopher Strachey|title=[[Fundamental Concepts in Programming Languages]]|journal=[[Higher-Order and Symbolic Computation]]|volume=13|pages=11–49|year=2000|doi=10.1023/A:1010000313106}}</ref><ref>{{ cite web | url = http://cm.bell-labs.com/cm/cs/who/dmr/bcpl.pdf | work = BCPL Reference Manual | title = BCPL Ternary operator (page 15) }}</ref> |
|||
It originally comes from [[CPL (programming language)|CPL]], in which equivalent syntax for <code>''e''<sub>1</sub> ? ''e''<sub>2</sub> : ''e''<sub>3</sub></code> was <code>''e''<sub>1</sub> → ''e''<sub>2</sub>, ''e''<sub>3</sub></code>.<ref>{{cite journal|first=Christopher|last=Strachey|author-link=Christopher Strachey|title=[[Fundamental Concepts in Programming Languages]]|journal=[[Higher-Order and Symbolic Computation]]|volume=13|pages=11–49|year=2000|doi=10.1023/A:1010000313106|s2cid=14124601}}</ref><ref>{{cite book | url = http://www.eah-jena.de/~kleine/history/languages/Richards-BCPL-ReferenceManual.pdf | title = The BCPL Reference Manual | year = 1967 | chapter = 5.5 Conditional expressions | pages = 16–17 | access-date = 2017-03-15 | archive-date = 2016-03-16 | archive-url = https://web.archive.org/web/20160316100234/http://www.eah-jena.de/~kleine/history/languages/Richards-BCPL-ReferenceManual.pdf | url-status = dead }}</ref> |
|||
Although many ternary operators are possible, the conditional operator is so common, and other ternary operators so rare, that the conditional operator is commonly referred to as ''the'' ternary operator. |
|||
==Variations== |
|||
The detailed semantics of "the" ternary operator as well as its syntax differs significantly from language to language. |
|||
A top level distinction from one language to another is whether the expressions permit [[side effect (computer science)|side effects]] (as in most procedural languages) and whether the language provides [[short-circuit evaluation]] semantics, whereby only the selected expression is evaluated (most standard operators in most languages evaluate all arguments). |
|||
If the language supports expressions with side effects but does not specify short-circuit evaluation, then a further distinction exists about which expression evaluates first—if the language guarantees any specific order (bear in mind that the conditional also counts as an expression). |
|||
Furthermore, 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 behavior|undefined]] (any value at all at the whim of the compiler in the face of side effects, or even a crash). |
|||
If the language does not permit side-effects in expressions (common in functional languages), then the order of evaluation has no value semantics—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 {{code|1=variable = condition ? expr1 : expr2;}} can have subtly different semantics than the block conditional form {{code|1=if (condition) { variable = expr1; } else { variable = expr2; } }} (in the C language—the syntax of the example given—these are in fact equivalent). |
|||
The associativity of nested ternary operators can also differ from language to language. In almost all languages, the ternary operator is [[right associative]] so that {{code|1=a == 1 ? "one" : a == 2 ? "two" : "many"}} evaluates intuitively as {{code|1=a == 1 ? "one" : (a == 2 ? "two" : "many")}}, but [[PHP]] in particular is notoriously left-associative,<ref>{{cite web |url=http://phpsadness.com/sad/30|title=Ternary operator associativity|last1=Wastl |first1=Eric |website=phpsadness.com |publisher=PHP Sadness |access-date=20 September 2017}}</ref> and evaluates as follows: {{code|1=(a == 1 ? "one" : a == 2) ? "two" : "many"}}, which is rarely what any programmer expects. (The given examples assume that the ternary operator has low [[operator precedence]], which is true in all C-family languages, and many others.) |
|||
==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 {{code|c(expr1,expr2)[1+condition]|r}} (this idiom is slightly more natural in languages with 0-origin subscripts). |
|||
Nested ternaries can be simulated as {{code|c(expr1,expr2,expr3)[which.first((c(cond1,cond2,TRUE))]|r}} where the function {{code|which.first}} 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 and promises|futures or promises]], then short-circuit evaluation can sometimes also be simulated in the context of a binary map operation. |
|||
==Conditional assignment== |
==Conditional assignment== |
||
Originally from ALGOL 60 the conditional assignment of ALGOL is: |
|||
variable := if condition then expression_1 else expression_2; |
|||
<code>?:</code> is used as follows: |
|||
{{code|?:}} is used as follows: |
|||
''condition'' ? ''value_if_true'' : ''value_if_false'' |
|||
''condition'' ? ''value_if_true'' : ''value_if_false'' |
|||
The ''condition'' is evaluated ''true'' or ''false'' as a [[Boolean expression]]. On the basis of the evaluation of the Boolean condition, the entire expression returns ''value_if_true'' if ''condition'' is true, but ''value_if_false'' otherwise. Usually the two sub-expressions ''value_if_true'' and ''value_if_false'' must have the same type, which determines the type of the whole expression. The importance of this type-checking lies in the operator's most common use—in [[Conditional (programming)|conditional]] [[Assignment (computer science)|assignment]] statements. In this usage it appears as an [[Expression (programming)|expression]] on the right side of an assignment [[Statement (programming)|statement]], as follows: |
The ''condition'' is evaluated ''true'' or ''false'' as a [[Boolean expression]]. On the basis of the evaluation of the Boolean condition, the entire expression returns ''value_if_true'' if ''condition'' is true, but ''value_if_false'' otherwise. Usually the two sub-expressions ''value_if_true'' and ''value_if_false'' must have the same type, which determines the type of the whole expression. The importance of this type-checking lies in the operator's most common use—in [[Conditional (programming)|conditional]] [[Assignment (computer science)|assignment]] statements. In this usage it appears as an [[Expression (programming)|expression]] on the right side of an assignment [[Statement (programming)|statement]], as follows: |
||
Line 13: | Line 44: | ||
''variable'' = ''condition'' ? ''value_if_true'' : ''value_if_false'' |
''variable'' = ''condition'' ? ''value_if_true'' : ''value_if_false'' |
||
The ?: operator is similar to the way conditional expressions ('''if-then-else''' constructs) work in [[functional programming]] languages, like [[Scheme (programming language)|Scheme]], [[ML (programming language)|ML]], |
The ?: operator is similar to the way conditional expressions ('''if-then-else''' constructs) work in [[functional programming]] languages, like [[Scheme (programming language)|Scheme]], [[ML (programming language)|ML]], [[Haskell]], and [[XQuery]], since if-then-else forms an expression instead of a statement in those languages. |
||
==Usage== |
==Usage== |
||
The conditional operator's most common usage is to make a terse simple conditional assignment statement. For example, if we wish to implement some C code to change a shop's opening hours from |
The conditional operator's most common usage is to make a terse simple conditional assignment statement. For example, if we wish to implement some C code to change a shop's normal opening hours from 9 o'clock to 12 o'clock on Sundays, we may use |
||
<source lang="c"> |
|||
<syntaxhighlight lang="c"> |
|||
int opening_time = (day == WEEKEND) ? 9 : 12; |
|||
int opening_time = (day == SUNDAY) ? 12 : 9; |
|||
</source> |
|||
</syntaxhighlight> |
|||
instead of the more verbose |
instead of the more verbose |
||
<source lang="c"> |
|||
<syntaxhighlight lang="c"> |
|||
int opening_time; |
int opening_time; |
||
if (day == |
if (day == SUNDAY) |
||
opening_time = 9; |
|||
else |
|||
opening_time = 12; |
opening_time = 12; |
||
else |
|||
</source> |
|||
opening_time = 9; |
|||
The two forms are nearly equivalent. Keep in mind that the ?: is an expression and if-then-else is a statement. Note that neither ''value if true'' nor ''value if false'' expressions can be omitted from the conditional operator without an error report upon parsing. This contrasts with if..else ''statements'', where the else clause can be omitted. |
|||
</syntaxhighlight> |
|||
The two forms are nearly equivalent. Keep in mind that the {{code|?:}} is an expression and [[Conditional (programming)#If.E2.80.93then.28.E2.80.93else.29|if-then-else]] is a statement. Note that neither the ''true'' nor ''false'' portions can be omitted from the conditional operator without an error report upon parsing. This contrasts with if-then-else statements, where the else clause can be omitted. |
|||
Most of the languages emphasizing [[functional programming]] don't need such an operator as their regular conditional expression(s) is an expression in the first place e.g. the [[Scheme (programming language)|Scheme]] expression <code>(if (> a b) a b)</code> is equivalent in semantics to the C expression <code>(a > b) ? a : b</code>. This is also the case in many imperative languages, starting with [[ALGOL]] where it is possible to write <code>result := if a > b then a else b</code>, or [[Smalltalk]] (<code>result := (a > b) ifTrue: [ a ] ifFalse: [ b ]</code>) or [[Ruby (programming language)|Ruby]] (<code>result = if a > b then a else b end</code>, although <code>result = a > b ? a : b</code> works as well). |
|||
Most of the languages emphasizing [[functional programming]] don't need such an operator as their regular conditional expression(s) is an expression in the first place e.g. the [[Scheme (programming language)|Scheme]] expression {{code|2=scheme|(if (> a b) a b)}} is equivalent in semantics to the C expression {{code|2=c|(a > b) ? a : b}}. This is also the case in many imperative languages, starting with [[ALGOL]] where it is possible to write {{code|1=result := if a > b then a else b}}, or [[Smalltalk]] ({{code|2=smalltalk|1=result := (a > b) ifTrue: [ a ] ifFalse: [ b ]}}) or [[Ruby (programming language)|Ruby]] ({{code|2=ruby|1=result = if a > b then a else b end}}, although {{code|2=ruby|1=result = a > b ? a : b}} works as well). |
|||
===Actionscript 3=== |
|||
<source lang=actionscript3> |
|||
Note that some languages may evaluate ''both'' the true- and false-expressions, even though only one or the other will be assigned to the variable. This means that if the true- or false-expression contain a function call, that function may be called and executed (causing any related side-effects due to the function's execution), regardless of whether or not its result will be used. Programmers should consult their programming language specifications or test the ternary operator to determine whether or not the language will evaluate both expressions in this way. If it does, and this is not the desired behaviour, then an [[Conditional (programming)#If.E2.80.93then.28.E2.80.93else.29|if-then-else statement]] should be used. |
|||
===ActionScript 3=== |
|||
<syntaxhighlight lang="actionscript3"> |
|||
condition ? value_if_true : value_if_false |
condition ? value_if_true : value_if_false |
||
</syntaxhighlight> |
|||
</source> |
|||
===Ada=== |
|||
The 2012 edition of [[Ada (programming language)|Ada]] has introduced conditional expressions (using {{code|if}} and {{code|case}}), as part of an enlarged set of expressions including quantified expressions and expression functions. The Rationale for Ada 2012<ref>{{cite web|title=Rationale for Ada 2012|url=http://www.ada-auth.org/standards/12rat/html/Rat12-2-1.html|publisher=ACAA|access-date=10 December 2015}}</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 {{code|else}} part may be omitted, the value being True. Multiple conditions may chained using {{code|elsif}}. |
|||
=== ALGOL 60 === |
|||
ALGOL 60 introduced [[ALGOL 60#Expressions and compound statements|conditional expressions]] (thus ternary conditionals) to imperative programming languages. |
|||
'''if''' <boolean expression> '''then''' <expression> '''else''' <expression> |
|||
Rather than a conditional statement: |
|||
<syntaxhighlight lang="pascal"> |
|||
integer opening_time; |
|||
if day = Sunday then |
|||
opening_time := 12; |
|||
else |
|||
opening_time := 9; |
|||
</syntaxhighlight> |
|||
the programmer could use the conditional expression to write more succinctly: |
|||
<syntaxhighlight lang="pascal"> |
|||
integer opening_time; |
|||
opening_time := if day = Sunday then 12 else 9; |
|||
</syntaxhighlight> |
|||
===ALGOL 68=== |
===ALGOL 68=== |
||
Both [[ALGOL 68]]'s [[ALGOL 68#Expressions and compound statements|choice clauses]] ('''if''' and the '''case''' clauses) provide the coder with a choice of ''either'' the "'''bold'''" syntax or the "''brief''" form. |
Both [[ALGOL 68]]'s [[ALGOL 68#Expressions and compound statements|choice clauses]] ('''if''' and the '''case''' clauses) provide the coder with a choice of ''either'' the "'''bold'''" syntax or the "''brief''" form. |
||
* Single '''if''' choice clause: |
* Single '''if''' choice clause: |
||
'''if''' condition '''then''' statements [ '''else''' statements ] '''fi''' |
|||
*: "''brief''" form: <code>( condition | statements | statements )</code> |
|||
* Chained '''if''' choice clause: |
* Chained '''if''' choice clause: |
||
'''if''' condition1 '''then''' statements '''elif''' condition2 '''then''' statements [ '''else''' statements ] '''fi''' |
|||
*: "''brief''" form: <code>( condition1 | statements |: condition2 | statements | statements )</code> |
|||
===APL=== |
|||
With the following syntax, both expressions are evaluated (with {{code|value_if_false}} evaluated first, then {{code|condition}}, then {{code|value_if_false}}): |
|||
<syntaxhighlight lang="apl"> |
|||
result ← value_if_true ⊣⍣ condition ⊢ value_if_false |
|||
</syntaxhighlight> |
|||
This alternative syntax provides short-circuit evaluation: |
|||
<syntaxhighlight lang="apl"> |
|||
result ← { condition : expression_if_true ⋄ expression_if_false } ⍬ |
|||
</syntaxhighlight> |
|||
===AWK=== |
|||
<syntaxhighlight lang="awk"> |
|||
result = condition ? value_if_true : value_if_false |
|||
</syntaxhighlight> |
|||
===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 {{code|1="$a" = "$b"}} can be any condition {{code|[[ … ]]}} construct can evaluate. Instead of the {{code|[[ … ]]}} 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=== |
===C=== |
||
A traditional if-else construct in [[C (programming language)|C |
A traditional if-else construct in [[C (programming language)|C]] is written: |
||
<source lang="c"> |
|||
<syntaxhighlight lang="c"> |
|||
if (a > b) { |
if (a > b) { |
||
result = x; |
result = x; |
||
} |
} |
||
else { |
|||
result = y; |
result = y; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
This can be rewritten as the following statement: |
This can be rewritten as the following statement: |
||
< |
<syntaxhighlight lang="c"> |
||
result = a > b ? x : y; |
result = a > b ? x : y; |
||
</syntaxhighlight> |
|||
</source> |
|||
As in the if-else construct only one of the expressions 'x' and 'y' is evaluated. This is significant if the evaluation of 'x' or 'y' has [[Side effect (computer science)|side effect]]s.<ref name="ISO/IEC 9899:1999">ISO.IEC 9899:1999 (E) 6.5.15.4</ref> The behaviour is undefined if an attempt is made to use the result of the conditional operator as an [[Value (computer science)#lrvalue|lvalue]].<ref name="ISO/IEC 9899:1999"/> |
|||
A [[GNU Project|GNU]] extension to C allows omitting the second operand, and using implicitly the first operand as the second also: |
A [[GNU Project|GNU]] extension to C allows omitting the second operand, and using implicitly the first operand as the second also: |
||
<source lang="c"> |
|||
<syntaxhighlight lang="c"> |
|||
a = x ? : y; |
a = x ? : y; |
||
</syntaxhighlight> |
|||
</source> |
|||
The expression is equivalent to |
The expression is equivalent to |
||
<source lang="c"> |
|||
<syntaxhighlight lang="c"> |
|||
a = x ? x : y; |
a = x ? x : y; |
||
</syntaxhighlight> |
|||
</source> |
|||
except that if ''x'' is an expression, it is evaluated only once. The difference is significant if evaluating the expression has [[Side effect (computer science)|side effect]]s. |
|||
except that expressions ''a'' and ''x'' are evaluated only once. The difference is significant if evaluating the expression has side effects. This shorthand form is sometimes known as the [[Elvis operator]] in other languages. |
|||
[[C Sharp (programming language)|C#]] and [[Perl]] provide similar functionality with their [[null coalescing operator]]. |
|||
<source lang="csharp"> |
|||
===C#=== |
|||
a = x ?? y; |
|||
In [[C Sharp (programming language)|C#]], if condition is true, first expression is evaluated and becomes the result; if false, the second expression is evaluated and becomes the result. As with [[Java (programming language)|Java]] only one of two expressions is ever evaluated. |
|||
</source> |
|||
(Unlike the above usage of "x ?: y", ?? will only test if ''x'' is non-null, as opposed to non-false.) |
|||
<syntaxhighlight lang="c"> |
|||
// condition ? first_expression : second_expression; |
|||
static double sinc(double x) |
|||
{ |
|||
return x != 0.0 ? Math.Sin(x) / x : 1.0; |
|||
} |
|||
</syntaxhighlight> |
|||
===C++=== |
===C++=== |
||
Unlike in [[C (programming language)|C]], the precedence of the {{code|?:}} operator in [[C++]] is the same as that of the assignment operator ({{code|1==}} or {{code|1=OP=}}), and it can return an lvalue.<ref>{{cite web |url=http://en.cppreference.com/enwiki/w/cpp/language/operator_precedence#Notes |title=C++ Operator Precedence |at=section: "Notes" |website=en.cppreference.com }}</ref> This means that expressions like {{code|1=q ? a : b = c}} and {{code|1=(q ? a : b) = c}} are both legal and are parsed differently, the former being equivalent to {{code|1=q ? a : (b = c)}}. |
|||
In [[C++]] there are conditional assignment situations where use of the ''if-else'' statement is impossible, since this language explicitly distinguishes between [[initialization (programming)|initialization]] and [[assignment (programming)|assignment]]. In such case it is always possible to use a function call, but this can be cumbersome and inelegant. For example, to pass conditionally different values as an argument for a constructor of a field or a base class, it is impossible to use a plain ''if-else'' statement; in this case we can use a conditional assignment expression, or a function call. Mind also that some types allow initialization, but do not allow assignment, or even the assignment operator does totally different things than the constructor. The latter is true for reference types, for example: |
|||
<source lang="cpp"> |
|||
In [[C++]] there are conditional assignment situations where use of the ''if-else'' statement is impossible, since this language explicitly distinguishes between [[initialization (programming)|initialization]] and [[assignment (programming)|assignment]]. In such case it is always possible to use a function call, but this can be cumbersome and inelegant. For example, to pass conditionally different values as an argument for a constructor of a field or a base class, it is impossible to use a plain ''if-else'' statement; in this case we can use a '''conditional assignment expression''', or a function call. Bear in mind also that some types allow initialization, but do not allow assignment, or even that the assignment operator and the constructor do totally different things. This last is true for reference types, for example: |
|||
<syntaxhighlight lang="cpp" highlight="16"> |
|||
#include <iostream> |
#include <iostream> |
||
#include <fstream> |
#include <fstream> |
||
#include <string> |
#include <string> |
||
int main(int argc, char *argv[]) |
int main(int argc, char *argv[]) |
||
{ |
{ |
||
std::string name; |
std::string name; |
||
std::ofstream fout; |
std::ofstream fout; |
||
if (argc > 1 && argv[1]) |
|||
if (argc > 1 && argv[1]) |
|||
{ |
|||
name = argv[1]; |
{ |
||
name = argv[1]; |
|||
fout.open(name.c_str(), std::ios::out | std::ios::app); |
fout.open(name.c_str(), std::ios::out | std::ios::app); |
||
} |
} |
||
std::ostream &sout = name.empty() ? std::cout : fout; |
|||
sout << "Hello, world!\n"; |
|||
return 0; |
|||
std::ostream &sout = name.empty() ? cout : fout; |
|||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
In this case, using an '''if-else''' statement in place of the {{code|?:}} operator forces the target of the assignment to be declared outside of the branches as a [[Pointer (computer programming)|pointer]], which can be freely rebound to different objects. |
|||
<syntaxhighlight lang="cpp" highlight="16"> |
|||
std::ostream* sout = &fout; |
|||
if (name.empty()) { |
|||
sout = &std::cout; |
|||
} |
|||
*sout << "Hello, world!\n"; |
|||
</syntaxhighlight> |
|||
In this simple example, the {{code|sout}} pointer can be initialized to a default value, mitigating the risk of leaving pointers uninitialized or [[Null pointer|null]]. Nevertheless, there are cases when no good default exists or creating a default value is expensive. More generally speaking, keeping track of a nullable pointer increases cognitive load. Therefore, only conditional assignment to a reference through the {{code|?:}} operator conveys the semantics of ''Initializing a variable from only one of two choices based on a predicate'' appropriately. |
|||
In this case there's no possibility to replace the use of ?: operator with '''if-else''' statement. (Although, we can replace the use of ?: with a function call, inside of which can be an ''if-else'' statement.) |
|||
Furthermore, the conditional operator can yield an lvalue, i.e. a value to which another value can be assigned. Consider the following example: |
Furthermore, the conditional operator can yield an lvalue, i.e. a value to which another value can be assigned. Consider the following example: |
||
< |
<syntaxhighlight lang="cpp" line highlight="8"> |
||
#include <iostream> |
#include <iostream> |
||
int main () |
|||
int main(int argc, char *argv[]) |
|||
{ |
{ |
||
int a |
int a = 0; |
||
int b = 0; |
|||
(argc > 1 ? a : b) = 1; |
|||
(cond ? a : b) = 1; |
|||
std::cout << "a |
std::cout << "a: " << a |
||
<< "b |
<< " b: " << b |
||
<< '\n'; |
|||
return 0; |
|||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
In this example, if the boolean |
In this example, if the boolean expression {{code|argc > 1}} yields the value {{code|true}} on line 8, the value {{code|1}} is assigned to the variable {{code|a}}, otherwise the value {{code|1}} is assigned to the variable {{code|b}}. |
||
=== |
===CFML=== |
||
Example of the {{code|?:}} operator in [[CFML]]: |
|||
In [[C Sharp (programming language)|C#]], if condition is true, first expression is evaluated and becomes the result; if false, the second expression is evaluated and becomes the result. Only one of two expressions is ever evaluated. |
|||
<source lang="c">//condition ? first_expression : second_expression; |
|||
<syntaxhighlight lang="cfc"> |
|||
static double sinc(double x) |
|||
result = randRange(0,1) ? "heads" : "tails"; |
|||
{ |
|||
</syntaxhighlight> |
|||
return x != 0.0 ? Math.Sin(x)/x : 1.0; |
|||
Roughly 50% of the time the {{code|randRange()}} expression will return 1 (true) or 0 (false); meaning result will take the value "heads" or "tails" respectively. |
|||
====Lucee, Railo, and ColdFusion 11-specific==== |
|||
[[Lucee]], [[Railo]], and ColdFusion 11 also implement the Elvis operator, {{code|?:}} which will return the value of the expression if it is not-null, otherwise the specified default. |
|||
Syntax: |
|||
<syntaxhighlight lang="CFC"> |
|||
result = expression ?: value_if_expression_is_null |
|||
</syntaxhighlight> |
|||
Example: |
|||
<syntaxhighlight lang="CFC"> |
|||
result = f() ?: "default"; |
|||
// where... |
|||
function f(){ |
|||
if (randRange(0,1)){ // either 0 or 1 (false / true) |
|||
return "value"; |
|||
} |
|||
} |
} |
||
</source> |
|||
writeOutput(result); |
|||
===ColdFusion Markup Language=== |
|||
</syntaxhighlight> |
|||
A [[ColdFusion Markup Language]] (CFML) example, for the [[Railo]] compiler: |
|||
The function {{code|f()}} will return {{code|value}} roughly 50% of the time, otherwise will not return anything. If {{code|f()}} returns "value", {{code|result}} will take that value, otherwise will take the value "default". |
|||
<source lang="cfm"> |
|||
<cfscript> |
|||
/** EXAMPLE 1 **/ |
|||
arg = "T"; |
|||
vehicle = ( ( arg == 'B' ) ? 'bus' : |
|||
( arg == 'A' ) ? 'airplane' : |
|||
( arg == 'T' ) ? 'train' : |
|||
( arg == 'C' ) ? 'car' : |
|||
( arg == 'H' ) ? 'horse' : |
|||
'feet' ); |
|||
writeOutput(vehicle); |
|||
// outputs 'train' |
|||
===CoffeeScript=== |
|||
/** EXAMPLE 2 **/ |
|||
Example of using this operator in [[CoffeeScript]]: |
|||
price = 1000; |
|||
hasPrice = ( price > 0 ) ? true : false; |
|||
// returns true |
|||
</cfscript> |
|||
</source> |
|||
<syntaxhighlight lang="coffeescript"> |
|||
=== Common Lisp === |
|||
if 1 is 2 then "true value" else "false value" |
|||
</syntaxhighlight> |
|||
Returns "false value". |
|||
===Common Lisp=== |
|||
Assignment using a conditional expression in [[Common Lisp]]: |
Assignment using a conditional expression in [[Common Lisp]]: |
||
<source lang="lisp"> |
|||
(setf result (if (> a b) x y)) |
|||
</source> |
|||
<syntaxhighlight lang="lisp"> |
|||
Imperative form: |
|||
(setq result (if (> a b) x y)) |
|||
<source lang="lisp"> |
|||
</syntaxhighlight> |
|||
Alternative form: |
|||
<syntaxhighlight lang="lisp"> |
|||
(if (> a b) |
(if (> a b) |
||
( |
(setq result x) |
||
( |
(setq result y)) |
||
</syntaxhighlight> |
|||
</source> |
|||
===Crystal=== |
|||
Example of using this operator in [[Crystal (programming language)|Crystal]]: |
|||
<syntaxhighlight lang="crystal"> |
|||
1 == 2 ? "true value" : "false value" |
|||
</syntaxhighlight> |
|||
Returns {{code|"false value"}}. |
|||
The Crystal compiler transforms conditional operators to {{code|if}} expressions, so the above is semantically identical to: |
|||
<syntaxhighlight lang="crystal"> |
|||
if 1 == 2 |
|||
"true value" |
|||
else |
|||
"false value" |
|||
end |
|||
</syntaxhighlight> |
|||
===Dart=== |
|||
The [[Dart (programming language)|Dart]] programming language's syntax belongs to the [[C (programming language)|C]] family, primarily inspired by languages like Java, C# and JavaScript, which means it has inherited the traditional {{code|?:}} syntax for its conditional expression. |
|||
Example: |
|||
<syntaxhighlight lang="Dart"> |
|||
return x.isEven ? x ~/ 2 : x * 3 + 1; |
|||
</syntaxhighlight> |
|||
Like other conditions in Dart, the expression before the {{code|?}} must evaluate to a [[Boolean]] value. |
|||
The Dart syntax uses both {{code|?}} and {{code|:}} in various other ways, which causes ambiguities in the language grammar. An expression like: |
|||
<syntaxhighlight lang="Dart"> |
|||
{ x as T ? [1] : [2] } |
|||
</syntaxhighlight> |
|||
could be parsed as either a "set literal" containing one of two lists ''or'' as a "map literal" <code>{((x as T?)[1]) : [2]}</code>. The language always chooses the conditional expression in such situations. |
|||
Dart also has a second ternary operator, the {{code|1=[]=}} operator commonly used for setting values in lists or maps, which makes the term "the ternary operator" ambiguous in a Dart context. |
|||
===Delphi=== |
|||
In [[Object Pascal|Delphi]] the {{code|IfThen}} function can be used to achieve the same as {{code|?:}}. If the {{code|System.Math}} library is used, the {{code|IfThen}} function returns a numeric value such as an [[Integer (computer science)|Integer]], [[Double precision|Double]] or Extended. If the {{code|System.StrUtils}} library is used, this function can also return a [[string (computer science)|string]] value. |
|||
Using {{code|System.Math}} |
|||
<syntaxhighlight lang="Delphi"> |
|||
function IfThen(AValue: Boolean; const ATrue: Integer; const AFalse: Integer): Integer; |
|||
function IfThen(AValue: Boolean; const ATrue: Int64; const AFalse: Int64): Int64; |
|||
function IfThen(AValue: Boolean; const ATrue: UInt64; const AFalse: UInt64): UInt64; |
|||
function IfThen(AValue: Boolean; const ATrue: Single; const AFalse: Single): Single; |
|||
function IfThen(AValue: Boolean; const ATrue: Double; const AFalse: Double): Double; |
|||
function IfThen(AValue: Boolean; const ATrue: Extended; const AFalse: Extended): Extended; |
|||
</syntaxhighlight> |
|||
Using the {{code|System.StrUtils}} library |
|||
<syntaxhighlight lang="Delphi"> |
|||
function IfThen(AValue: Boolean; const ATrue: string; AFalse: string = ''): string; |
|||
</syntaxhighlight> |
|||
Usage example: |
|||
<syntaxhighlight lang="Delphi"> |
|||
function GetOpeningTime(Weekday: Integer): Integer; |
|||
begin |
|||
{ This function will return the opening time for the given weekday: 12 for Sundays, 9 for other days } |
|||
Result := IfThen((Weekday = 1) or (Weekday = 7), 12, 9); |
|||
end; |
|||
</syntaxhighlight> |
|||
Unlike a true ternary operator however, both of the results are evaluated prior to performing the comparison. For example, if one of the results is a call to a function which inserts a row into a database table, that function will be called whether or not the condition to return that specific result is met. |
|||
=== Eiffel === |
|||
The original Eiffel pure OO language from 1986 did not have conditional expressions. Extensions to Eiffel to integrate the style and benefits of functional in the form of [[Eiffel_(programming_language)#Agents|agents]] (closely associated with functional lambdas) were proposed and implemented in 2014. |
|||
'''if''' <boolean expression> '''then''' <expression> '''else''' <expression> |
|||
<syntaxhighlight lang="eiffel"> |
|||
opening_time: INTEGER |
|||
opening_time := if day = Sunday then 12 else 9 |
|||
</syntaxhighlight> |
|||
===F#=== |
|||
In [[F Sharp (programming language)|F#]] the built-in syntax for if-then-else is already an expression that always must return a value. |
|||
<syntaxhighlight lang="fsharp"> |
|||
let num = if x = 10 then 42 else 24 |
|||
</syntaxhighlight> |
|||
F# has a special case where you can omit the else branch if the return value is of type unit. This way you can do side-effects, without using an else branch. |
|||
<syntaxhighlight lang="fsharp"> |
|||
if x = 10 then |
|||
printfn "It is 10" |
|||
</syntaxhighlight> |
|||
But even in this case, the if expression would return unit. You don't need to write the else branch, because the compiler will assume the unit type on else. |
|||
===FORTH=== |
|||
Since [[Forth (programming language)|FORTH]] is a stack-oriented language, and any expression can leave a value on the stack, all {{code|IF}}/{{code|ELSE}}/{{code|THEN}} sequences can generate values: |
|||
<syntaxhighlight lang="forth"> |
|||
: test ( n -- n ) 1 AND IF 22 ELSE 42 THEN ; |
|||
</syntaxhighlight> |
|||
This word takes 1 parameter on the stack, and if that number is odd, leaves 22. If it's even, 42 is left on the stack. |
|||
===Fortran=== |
|||
With the additions to the code in the 1995 release, the ternary operator was added to the [[Fortran]] compiler as the intrinsic function {{code|merge}}: |
|||
<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. |
|||
=== FreeMarker === |
|||
This built-in exists since [[FreeMarker]] 2.3.20. |
|||
Used like <code>''booleanExp''?then(''whenTrue'', ''whenFalse'')</code>, fills the same role as the ternary operator in C-like languages. |
|||
<syntaxhighlight lang="text"> |
|||
<#assign x = 10> |
|||
<#assign y = 20> |
|||
<#-- Prints the maximum of x and y: --> |
|||
${(x > y)?then(x, y)} |
|||
</syntaxhighlight> |
|||
===Go=== |
|||
There is no ternary if in [[Go (programming language)|Go]], so use of the full if statement is always required.<ref name="go-ternary"/> |
|||
===Haskell=== |
|||
The built-in if-then-else syntax is inline: the expression |
|||
<syntaxhighlight lang="haskell"> |
|||
if predicate then expr1 else expr2 |
|||
</syntaxhighlight> |
|||
has type |
|||
<syntaxhighlight lang="haskell"> |
|||
Bool -> a -> a -> a |
|||
</syntaxhighlight> |
|||
The base library also provides the function {{code|Data.Bool.bool}}: |
|||
<syntaxhighlight lang="haskell"> |
|||
bool :: a -> a -> Bool -> a |
|||
</syntaxhighlight> |
|||
In both cases, no special treatment is needed to ensure that only the selected expression is evaluated, since Haskell is non-strict by default. This also means an operator can be defined that, when used in combination with the {{code|$}} operator, functions exactly like {{code|?:}} in most languages: |
|||
<syntaxhighlight lang="haskell"> |
|||
(?) :: Bool -> a -> a -> a |
|||
(?) pred x y = if pred then x else y |
|||
infix 1 ? |
|||
-- example (vehicle will evaluate to "airplane"): |
|||
arg = 'A' |
|||
vehicle = arg == 'B' ? "boat" $ |
|||
arg == 'A' ? "airplane" $ |
|||
arg == 'T' ? "train" $ |
|||
"car" |
|||
</syntaxhighlight> |
|||
However, it is more idiomatic to use [https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-460003.13 pattern guards] |
|||
<syntaxhighlight lang="haskell"> |
|||
-- example (vehicle will evaluate to "airplane"): |
|||
arg = 'A' |
|||
vehicle | arg == 'B' = "boat" |
|||
| arg == 'A' = "airplane" |
|||
| arg == 'T' = "train" |
|||
| otherwise = "car" |
|||
</syntaxhighlight> |
|||
===Java=== |
===Java=== |
||
In [[Java (programming language)|Java]] this expression evaluates to: |
In [[Java (programming language)|Java]] this expression evaluates to: |
||
<syntaxhighlight lang="java"> |
|||
<code>if foo is selected assign selected foo to bar else assign selected baz to bar.</code> |
|||
// If foo is selected, assign selected foo to bar. If not, assign baz to bar. |
|||
<source lang="java"> |
|||
Object bar = foo.isSelected() ? |
Object bar = foo.isSelected() ? foo : baz; |
||
</syntaxhighlight> |
|||
</source> |
|||
Note that Java, in a manner similar to C#, only evaluates the used expression and will not evaluate the unused expression.<ref name="java">Java 7 Specification: [http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25 15.25 Conditional Operator ? : ]</ref> |
|||
===Julia=== |
|||
In [[Julia (programming language)|Julia]], "Note that the spaces around {{code|?}} and {{code|:}} are mandatory: an expression like {{code|a?b:c}} is not a valid ternary expression (but a newline is acceptable after both the {{code|?}} and the {{code|:}})."<ref>{{Cite web|url=https://docs.julialang.org/en/v1/manual/control-flow/#man-conditional-evaluation-1|title=Control Flow · The Julia Language|website=docs.julialang.org|access-date=2020-03-12}}</ref> |
|||
===JavaScript=== |
===JavaScript=== |
||
The conditional operator in [[JavaScript]] is similar to that of [[C++]] and [[Java (programming language)|Java]], except for the fact the middle expression cannot be a comma expression. Also, as in C++, but unlike in [[C (programming language)|C]] or [[Perl]], it will not bind tighter than an assignment to its right—{{code|1=q ? a : b = c}} is equivalent to {{code|1=q ? a : (b = c)}} instead of {{code|1=(q ? a : b) = c}}.<ref>{{cite web|title=ECMA-262 Edition 5.1|url=http://www.ecma-international.org/ecma-262/5.1/#sec-11.12|work=Ecma Language Specification|publisher=Ecma International|access-date=7 September 2013}}</ref> |
|||
The conditional operator in [[JavaScript]] has the same syntax and precedence structure as in the other [[BCPL]]-derived variants, but a significant difference exists in the semantics: it returns an [[Value (computer science)|l-value]]. (This situation apparently was improperly specified in the original JavaScript specification,<ref>{{cite web |url= http://hepunx.rl.ac.uk/~adye/jsspec11/expr.htm#1004949 |work= JavaScript Language Specification |last= Eich |first= Brendan |authorlink= Brendan Eich |coauthors= C. Rand McKinney |title= Conditional Operator (section 4.14) |date= 1996-11-18 |accessdate= 2010-08-29}}</ref> but has been clarified in the December 2009 [[ECMA-262]] specification.<ref>{{cite web |title= Conditional Operator (section 11.12, page 93) |work= ECMAScript Language Specification |date= 2009-12 |url= http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf |format= PDF |accessdate= 2010-08-29| archiveurl= http://web.archive.org/web/20100816042313/http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf| archivedate= 16 August 2010 <!--DASHBot-->| deadurl= no}}</ref>) |
|||
< |
<syntaxhighlight lang="javascript"> |
||
var |
var timeout = settings === null ? 1000 : settings.timeout; |
||
</syntaxhighlight> |
|||
</source> |
|||
Just like C# and Java, the expression will only be evaluated if, and only if, the expression is the matching one for the condition given; the other expression will not be evaluated. |
|||
=== Lisp === |
|||
As the first functional programming language, [[Lisp (programming language)|Lisp]] naturally has conditional expressions since there are no statements and thus not conditional statements. The form is: |
|||
<syntaxhighlight lang="LISP">(if test-expression then-expression else-expression)</syntaxhighlight> |
|||
Hence: |
|||
<syntaxhighlight lang="LISP">(if day = Sunday 12 9)</syntaxhighlight> |
|||
=== Kotlin === |
|||
Kotlin does not include the traditional {{code|?:}} ternary operator, however, {{code|if}}s can be used as expressions that can be assigned,<ref>{{Cite web|url=https://kotlinlang.org/docs/control-flow.html#if-expression|title=Kotlin Lang If Expression|website=kotlinlang.org|access-date=2021-04-25}}</ref> achieving the same results. Note that, as the complexity of one's conditional statement grows, the programmer might consider replacing their {{code|if}}-{{code|else}} expression with a {{code|when}} expression. |
|||
<syntaxhighlight lang="kotlin"> |
|||
val max = if (a > b) a else b |
|||
</syntaxhighlight> |
|||
===Lua=== |
=== Lua === |
||
Lua |
Lua does not have a traditional conditional operator. However, the short-circuiting behaviour of its {{code|and}} and {{code|or}} operators allows the emulation of this behaviour: |
||
<syntaxhighlight lang="lua"> |
<syntaxhighlight lang="lua"> |
||
Line 188: | Line 549: | ||
</syntaxhighlight> |
</syntaxhighlight> |
||
This will succeed unless |
This will succeed unless {{code|a}} is logically false (i.e. {{code|lang=lua|false}} or {{code|lang=lua|nil}}); in this case, the expression will always result in {{code|b}}. This can result in some surprising behaviour if ignored. |
||
There are also other variants that can be used, but they're generally more verbose: |
|||
===MySQL=== |
|||
This syntax is not SQL standard; it is MySQL specific. |
|||
<source lang="MySQL"> |
|||
IF(cond,a,b); |
|||
</source> |
|||
<syntaxhighlight lang="lua"> |
|||
===Oracle SQL=== |
|||
-- parentheses around the table literal are required |
|||
While Oracle doesn't provide an explicit conditional operator, it does have a [[Variadic function|variadic functional]] counterpart which operates similarly to a [[switch statement]] and can be used to emulate the conditional operator when testing for equality (more complicated logic can be encapsulated in a switch statement). |
|||
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 {{code|lang=lua|end}} keyword, and the {{code|lang=lua|else}} clause is required. One may optionally add {{code|lang=lua|elseif}} clauses. It's designed to replace the {{code|lang=lua|cond and a or b}} idiom and is expected to work properly in all cases.<ref>{{Cite web |title=Syntax § If-then-else expressions|url=https://luau-lang.org/syntax#if-then-else-expressions |access-date=2023-02-07 |website=Luau |language=en}}</ref> |
|||
<source lang="oracle8"> |
|||
-- General syntax takes case-result pairs, comparing against an expression, followed by a fall-back result: |
|||
DECODE(expression, case1, result1, |
|||
... |
|||
caseN, resultN, |
|||
resultElse) |
|||
<syntaxhighlight lang="lua"> |
|||
-- We can emulate the conditional operator by just selecting one case: |
|||
-- in Luau |
|||
DECODE(expression, condition, true, false) |
|||
var = if cond then a else b |
|||
</source> |
|||
-- with elseif clause |
|||
sign = if var < 0 then -1 elseif var == 0 then 0 else 1 |
|||
</syntaxhighlight> |
|||
=== Objective-C === |
|||
condition ? value_if_true : value_if_false |
|||
<syntaxhighlight lang="objective-c"> |
|||
int min = (1 < 2) ? 1 : 2; |
|||
</syntaxhighlight> |
|||
This will set the variable {{code|min}} to {{code|1}} because the condition {{code|(1 < 2)}} is {{code|true}}. |
|||
=== 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. |
|||
=== Perl === |
|||
A traditional if-else construct in [[Perl]] is written: |
|||
The <code>decode</code> function is, today, depreciated in favour of Oracle's full switch statement, <code>case</code>. This can be used in both Oracle SQL queries as well as PL/SQL blocks, whereas <code>decode</code> can only be used in the former. |
|||
<syntaxhighlight lang="perl"> |
|||
===Perl=== |
|||
A traditional if-else construct in [[Perl]] or [[PHP]] is written: |
|||
<source lang="perl"> |
|||
if ($a > $b) { |
if ($a > $b) { |
||
$result = $x; |
$result = $x; |
||
Line 220: | Line 597: | ||
$result = $y; |
$result = $y; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
Rewritten to use the ternary operator: |
|||
<source lang="perl"> |
|||
$result = ($a > $b) ? $x : $y; |
|||
</source> |
|||
Rewritten to use the conditional operator: |
|||
<source lang="perl">$secondVar = ($firstVar == 0) ? 0 : @array[0];</source> |
|||
<syntaxhighlight lang="perl"> |
|||
==== Perl 6 ==== |
|||
$result = $a > $b ? $x : $y; |
|||
Uses double "?" symbols and double "!" instead of ":" <ref name="perl6op">{{cite web|accessdate=2010-05-18|url=http://perlcabal.org/syn/S03.html#Conditional_operator_precedence/|title=Perl6 Operators|publisher=Larry Wall}}</ref>: |
|||
</syntaxhighlight> |
|||
<source lang="Perl"> |
|||
$result = ($a > $b) ?? $x !! $y; |
|||
The precedence of the conditional operator in Perl is the same as in C, not as in C++. This is conveniently of higher precedence than a [[comma operator]] but lower than the precedence of most operators used in expressions within the ternary operator, so the use of parentheses is rarely required.<ref name="perl5op">{{cite book|last1=Christiansen|first1=Tom|last2=Wall|first2=Larry|first3=Brian D|last3=Foy|authorlink1=Tom Christiansen|authorlink2=Larry Wall|authorlink3=Brian d foy|title=[[Programming Perl]]|date=February 2012|publisher=[[O'Reilly Media]]|location=Sebastopol, CA|isbn=978-0-596-00492-7 |page=123 |edition=Fourth |ref=Programming_Perl_v4 |chapter=Chapter 2 Unary and Binary Operators: Conditional Operator}}</ref> |
|||
</source> |
|||
Its associativity matches that of C and C++, not that of PHP. Unlike C but like C++, Perl allows the use of the conditional expression as an [[Value (computer science)#lrvalue|L-value]];<ref name="perldoc_perlop">{{cite web |title=perlop: Conditional Operator |url=https://perldoc.perl.org/perlop.html#Conditional-Operator|website=Perl Programming Documentation|last=Wall|first=Larry|author-link=Larry Wall|access-date=26 January 2019}}</ref> for example: |
|||
<syntaxhighlight lang="perl"> |
|||
$a > $b ? $x : $y = $result; |
|||
</syntaxhighlight> |
|||
will assign {{code|$result}} to either {{code|$x}} or {{code|$y}} depending on the logical expression's boolean result. |
|||
The respective precedence rules and associativities of the operators used guarantee that the version absent any parentheses is equivalent to this explicitly parenthesized version: |
|||
<syntaxhighlight lang="perl"> |
|||
(($a > $b) ? $x : $y) = $result; |
|||
</syntaxhighlight> |
|||
This is equivalent to the if-else version: |
|||
<syntaxhighlight lang="perl"> |
|||
if ($a > $b) { |
|||
$x = $result; |
|||
} else { |
|||
$y = $result; |
|||
} |
|||
</syntaxhighlight> |
|||
===PHP=== |
===PHP=== |
||
A simple [[PHP]] implementation is this: |
A simple [[PHP]] implementation is this: |
||
< |
<syntaxhighlight lang="php"> |
||
$abs = $value >= 0 ? $value : -$value; |
|||
<?php |
|||
</syntaxhighlight> |
|||
$valueOne = (5 > 1) ? true : false; |
|||
?> |
|||
</source> |
|||
Unlike most other programming languages, the conditional operator in [[PHP]] is [[operator associativity|left associative]] rather than right associative. Thus, given a value of '''T''' for '''arg''', the PHP code in the following example would yield the value '''horse''' instead of '''train''' as one might expect:<ref>{{cite web |url=http://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/#operators |title=PHP: a fractal of bad design |access-date=2015-10-04 |author=Eevee |date=2012-04-09 }}</ref> |
|||
<source lang="php"> |
|||
<syntaxhighlight lang="php"> |
|||
<?php |
<?php |
||
$arg = "T"; |
$arg = "T"; |
||
$vehicle = ( ( $arg == 'B' ) ? 'bus' : |
$vehicle = ( ( $arg == 'B' ) ? 'bus' : |
||
( $arg == 'A' ) ? 'airplane' : |
( $arg == 'A' ) ? 'airplane' : |
||
( $arg == 'T' ) ? 'train' : |
|||
( $arg == 'C' ) ? 'car' : |
|||
( $arg == 'H' ) ? 'horse' : |
|||
'feet' ); |
'feet' ); |
||
echo $vehicle; |
echo $vehicle; |
||
</syntaxhighlight> |
|||
?> |
|||
</source> |
|||
The reason is that nesting two conditional operators produces an oversized condition with the last two options as its branches: {{code|c1 ? o1 : c2 ? o2 : o3}} is really {{code|((c1 ? o1 : c2) ? o2 : o3)}}. This is acknowledged<ref>{{cite web |url=http://php.net/ternary#example-121 |title=Comparison Operators, Example #3: Non-obvious Ternary Behaviour |publisher=PHP website |access-date=2013-04-26}}</ref> and will probably not change.<ref>{{cite web |url=https://bugs.php.net/bug.php?id=61915 |title=PHP Bug #61915: incorrect associativity of ternary operator |quote=We can't fix this without breaking code |date=2012-05-02 |access-date=2013-04-26 |publisher=PHP website}}</ref> To avoid this, nested parenthesis are needed, as in this example: |
|||
< |
<syntaxhighlight lang="php"> |
||
<?php |
<?php |
||
$arg = "T"; |
$arg = "T"; |
||
$vehicle = |
$vehicle = $arg == "B" ? "bus" : |
||
($arg == "A" ? "airplane" : |
|||
($arg == "T" ? "train" : |
|||
($arg == "C" ? "car" : |
|||
($arg == "H" ? "horse" : |
|||
"feet")))); |
|||
echo $vehicle; |
echo $vehicle; |
||
</syntaxhighlight> |
|||
?> |
|||
</source> |
|||
This will produce the |
This will produce the result of '''train''' being printed to the output, analogous to a right associative conditional operator. |
||
===Powershell=== |
|||
In versions before Powershell 7 ternary operators are not supported <ref>{{cite web|url=https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_if?view=powershell-7.4#using-the-ternary-operator-syntax | title=about_If - Using the ternary operator syntax| date=7 June 2023}}</ref> however conditional syntax does support single line assignment: |
|||
<syntaxhighlight lang="powershell"> |
|||
==== PHP 5.3 ==== |
|||
$result = if $a -eq $b {"was true" } else {"was false"} |
|||
A second ternary operator (Elvis operator) in PHP 5.3 and higher |
|||
</syntaxhighlight> |
|||
<source lang="php"> |
|||
$a = $b ?: new B(); |
|||
</source> |
|||
If $b is not null, then $a is equal to $b, otherwise $a is equal to a new instance of B. This is equivalent to the older style |
|||
<source lang="php"> |
|||
if( !is_null( $b ) ){ |
|||
$a = $b; |
|||
}else{ |
|||
$a = new B(); |
|||
} |
|||
</source> |
|||
In Powershell 7+ traditional ternary operators are supported and follow the C# syntax:<ref>{{cite web|url=https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7.4#ternary-operator--if-true--if-false | title=about_Operators - Ternary operator| date=3 September 2024}}</ref> |
|||
Since PHP 5.3 there is a short-form of the conditional operator: |
|||
<syntaxhighlight lang="powershell"> |
|||
$result = $a -eq $b ? "was true" : "was false" |
|||
<source lang="php"> |
|||
</syntaxhighlight> |
|||
$c = $a ?: $b; // equivalent to $c = $a ? $a : $b; |
|||
</source> |
|||
===Python=== |
===Python=== |
||
Though it had been delayed for several years by disagreements over syntax, an operator for a conditional expression in [[Python (programming language)|Python]] was approved as [https://www.python.org/dev/peps/pep-0308/ Python Enhancement Proposal 308] and was added to the 2.5 release in September 2006. Python's conditional operator differs from the common {{code|?:}} operator in the order of its operands. The general form is:<ref>{{cite web|url=https://docs.python.org/3/reference/expressions.html#conditional-expressions | title=The Python Language Reference}}</ref> |
|||
[[Python (programming language)|Python]] uses a different syntax for this operator: |
|||
< |
<syntaxhighlight lang="python"> |
||
result = x if a > b else y |
|||
</syntaxhighlight> |
|||
</source> |
|||
This feature is not available for Python versions before 2.5, however. The [http://www.python.org/doc/faq/programming/#is-there-an-equivalent-of-c-s-ternary-operator Python programming FAQ] mentions several possible workarounds for these versions. |
|||
This form invites considering {{code|x}} as the normal value and {{code|y}} as an exceptional case. |
|||
Prior to Python 2.5 there were a number of ways to approximate a conditional operator (for example by indexing into a two element array), all of which have drawbacks as compared to the built-in operator. |
|||
=== Python === |
|||
Though it had been delayed for several years by disagreements over syntax, a ternary operator for a conditional expression in [[Python (programming language)|Python]] was approved as [http://www.python.org/dev/peps/pep-0308/ Python Enhancement Proposal 308] and was added to the 2.5 release in September 2006. Python's ternary operator for a conditional expression differs from the common <code>?:</code> operator in the order of its operands. The general form is: |
|||
===R=== |
|||
<source lang="python">result = x if a > b else y</source> |
|||
The traditional if-else construct in [[R (programming language)|R]] (which is an implementation of [[S (programming language)|S]]) is: |
|||
<syntaxhighlight lang="r"> |
|||
This form invites considering <code>x</code> as the normal value and <code>y</code> as an exceptional case. One can use the syntax |
|||
if (a < b) { |
|||
<source lang="python">(lambda:y, lambda:x)[a > b]()</source> |
|||
x <- "true" |
|||
as a workaround for code that also needs to run under Python versions before 2.5. Note that operands are [[Lazy evaluation|lazily evaluated]], it is possible to remove the lambdas and function calls but the operands will be eagerly evaluated which isn't consistent with other languages' ternary operators, e.g. by indexing a tuple, |
|||
} else { |
|||
<source lang="python">result = (y, x)[a > b]</source> |
|||
x <- "false" |
|||
or using an explicitly constructed dictionary: |
|||
} |
|||
<source lang="python">result = {True: x, False: y}[a > b]</source> |
|||
</syntaxhighlight> |
|||
If there is only one statement in each block, braces can be omitted, like in [[C (programming language)|C]]: |
|||
A less reliable but simpler to read alternative is to abuse the <code>and</code> and <code>or</code> operators and write |
|||
<source lang="python">result = (a > b) and x or y</source> |
|||
but this code would break if <code>x</code> could be a "falsy" value (<code>None</code>, <code>False</code>, <code>0</code>, an empty sequence or collection, …) as the expression would return <code>y</code> (whether it was truthy or falsy) instead of the (falsy) <code>x</code>. |
|||
A possible workaround is to make <code>x</code> and <code>y</code> lists or tuples, so they are never falsy, and then grab the first element of the resulting sequence as in the following |
|||
<source lang="python">result = ((a > b) and [x] or [y])[0]</source> |
|||
or |
|||
<source lang="python">result = ((a > b) and (x,) or (y,))[0]</source> |
|||
<syntaxhighlight lang="r"> |
|||
NB when wrapping the python ternary construct into a utility function, the unalterably eager nature of the more intuitive language construct for '''side-effect functions''' |
|||
if (a < b) |
|||
<source lang="python">func = lambda b,a1,a2 : (a1,a2)[not b] |
|||
x <- "true" |
|||
else |
|||
print "true" |
|||
x <- "false" |
|||
</syntaxhighlight> |
|||
def false(): |
|||
print "false" |
|||
return "falsely" |
|||
func(True, true(), false()) |
|||
true |
|||
false |
|||
'truly' |
|||
func(False, true(), false()) |
|||
true |
|||
false |
|||
'falsely'</source> |
|||
similar results from |
|||
<source lang="python">func = lambda b,a1,a2: a1 if b else a2 |
|||
func = lambda b,a1,a2: (b and [a1] or [a2])[0] |
|||
func = lambda b,a1,a2: (lambda:a1, lambda:a2)[not b]()</source> |
|||
as the correct call would be |
|||
<source lang="python"> |
|||
func(True, true, false)() |
|||
true |
|||
'truly' |
|||
func(False, true, false)() |
|||
false |
|||
'falsely'</source> |
|||
The code above can be written in the following non-standard condensed way: |
|||
however the python 2.5 construct is safer; calling the construct directly works more intuitively |
|||
<source lang="python">true() if True else false() |
|||
true |
|||
'truly' |
|||
true() if False else false() |
|||
false |
|||
'falsely'</source> |
|||
clearly the reason being that in the case of <source lang="python">func(True, true(), false())</source> the functions are called when sent as parameters rather than when returned from func() |
|||
<syntaxhighlight lang="r"> |
|||
===Ruby=== |
|||
x <- if (a < b) "true" else "false" |
|||
</syntaxhighlight> |
|||
There exists also the function {{code|ifelse}} that allows rewriting the expression above as: |
|||
<syntaxhighlight lang="r"> |
|||
x <- ifelse(a < b, "true", "false") |
|||
</syntaxhighlight> |
|||
The {{code|ifelse}} function is automatically vectorized. For instance: |
|||
<syntaxhighlight lang="rconsole"> |
|||
> ifelse(c (0, 2) < 1, "true", "false") |
|||
[1] "true" "false" |
|||
</syntaxhighlight> |
|||
===Raku=== |
|||
[[Raku (programming language)|Raku]] uses a doubled {{code|??}} symbol instead of single {{code|?}} |
|||
and a doubled {{code|!!}} symbol instead of {{code|:}}<ref name="perl6op">{{cite web|access-date=2010-05-18|url=http://perlcabal.org/syn/S03.html#Conditional_operator_precedence/|title=Perl6 Operators|last=Wall|first=Larry|author-link=Larry Wall|archive-url=https://web.archive.org/web/20090329224737/http://perlcabal.org/syn/S03.html#Conditional_operator_precedence/|archive-date=2009-03-29|url-status=dead}}</ref> |
|||
<syntaxhighlight lang="Perl"> |
|||
$result = $a > $b ?? $x !! $y; |
|||
</syntaxhighlight> |
|||
===Ruby=== |
|||
Example of using this operator in [[Ruby (programming language)|Ruby]]: |
Example of using this operator in [[Ruby (programming language)|Ruby]]: |
||
<source lang="ruby">1 == 2 ? "true value" : "false value"</source> |
|||
<syntaxhighlight lang="ruby"> |
|||
1 == 2 ? "true value" : "false value" |
|||
</syntaxhighlight> |
|||
Returns "false value". |
Returns "false value". |
||
=== Ruby === |
|||
A traditional if-else construct in [[Ruby (programming language)|Ruby]] is written:<ref name="pickaxe">Programming Ruby: [http://ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html#S4 Conditional Execution]</ref> |
A traditional if-else construct in [[Ruby (programming language)|Ruby]] is written:<ref name="pickaxe">Programming Ruby: [http://ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html#S4 Conditional Execution]</ref> |
||
<source lang="ruby"> |
|||
<syntaxhighlight lang="ruby"> |
|||
if a > b |
if a > b |
||
result = x |
result = x |
||
Line 377: | Line 755: | ||
result = y |
result = y |
||
end |
end |
||
</syntaxhighlight> |
|||
</source> |
|||
This could also be written as: |
This could also be written as: |
||
<source lang="ruby"> |
|||
<syntaxhighlight lang="ruby"> |
|||
result = if a > b |
result = if a > b |
||
x |
x |
||
Line 386: | Line 765: | ||
y |
y |
||
end |
end |
||
</syntaxhighlight> |
|||
</source> |
|||
These can be rewritten as the following statement: |
|||
<syntaxhighlight lang="ruby"> |
|||
These can be rewritten as the following ternary statement: |
|||
<source lang="ruby"> |
|||
result = a > b ? x : y |
result = a > b ? x : y |
||
</syntaxhighlight> |
|||
</source> |
|||
=== |
===Rust=== |
||
Being an [[expression-oriented programming language]], Rust's existing <code>if ''expr<sub>1</sub>'' else ''expr<sub>2</sub>''</code> syntax can behave as the traditional {{code|?:}} ternary operator does. Earlier versions of the language did have the {{code|?:}} operator but it was removed<ref>{{Cite web|url=https://github.com/rust-lang/rust/pull/1705|title = Remove Ternary Operator by pwoolcoc · Pull Request #1705 · rust-lang/Rust|website = [[GitHub]]}}</ref> due to duplication with {{code|if}}.<ref>{{Cite web|url=https://github.com/rust-lang/rust/issues/1698|title=Remove ternary operator · Issue #1698 · rust-lang/Rust|website=[[GitHub]]}}</ref> |
|||
A specific ternary operator for [[PL/SQL]] is not available, but a special case of the <code>[[PL/SQL#Conditional_Statements|CASE]]</code> expression works exactly as a ternary operator: |
|||
Note the lack of semi-colons in the code below compared to a more declarative {{code|if}}...{{code|else}} block, and the semi-colon at the end of the assignment to {{code|y}}. |
|||
<source lang="plsql"> |
|||
SELECT (CASE WHEN a > b THEN x ELSE y END) AS "Ternary_Example" |
|||
<syntaxhighlight lang="rust"> |
|||
FROM DUAL; |
|||
let x = 5; |
|||
</source> |
|||
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 {{code|match}} expression: |
|||
<syntaxhighlight lang="rust"> |
|||
let y = match x { |
|||
5 => 10, |
|||
_ => 15, |
|||
}; |
|||
</syntaxhighlight> |
|||
===Scheme=== |
|||
Same as in Common Lisp. Every expression has a value. Thus the builtin {{code|if}} can be used: |
|||
<syntaxhighlight lang="scheme"> |
|||
(let* ((x 5) |
|||
(y (if (= x 5) 10 15))) |
|||
...) |
|||
</syntaxhighlight> |
|||
===Smalltalk=== |
|||
Every expression (message send) has a value. Thus {{code|ifTrue:ifFalse:}} can be used: |
|||
<syntaxhighlight lang="scheme"> |
|||
|x y| |
|||
x := 5. |
|||
y := (x == 5) ifTrue:[10] ifFalse:[15]. |
|||
</syntaxhighlight> |
|||
===SQL=== |
|||
The SQL {{code|CASE}} 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> |
|||
====MySQL==== |
|||
In addition to the standard {{code|CASE}} expression, MySQL provides an {{code|IF}} function as an extension: |
|||
<syntaxhighlight lang="MySQL"> |
|||
IF(cond, a, b); |
|||
</syntaxhighlight> |
|||
====SQL Server==== |
|||
In addition to the standard {{code|CASE}} expression, SQL Server (from 2012) provides an {{code|IIF}} function: |
|||
<syntaxhighlight lang="T-SQL"> |
|||
IIF(condition, true_value, false_value) |
|||
</syntaxhighlight> |
|||
====Oracle SQL==== |
|||
In addition to the standard {{code|CASE}} expression, Oracle has a [[variadic function]]al counterpart which operates similarly to a [[switch statement]] and can be used to emulate the conditional operator when testing for equality. |
|||
<syntaxhighlight lang="sql"> |
|||
-- General syntax takes case-result pairs, comparing against an expression, followed by a fall-back result: |
|||
DECODE(expression, case1, result1, |
|||
... |
|||
caseN, resultN, |
|||
resultElse) |
|||
-- We can emulate the conditional operator by just selecting one case: |
|||
DECODE(expression, condition, true, false) |
|||
</syntaxhighlight> |
|||
The {{code|DECODE}} function is, today, deprecated in favour of the standard {{code|CASE}} expression. This can be used in both Oracle SQL queries as well as [[PL/SQL]] blocks, whereas {{code|decode}} can only be used in the former. |
|||
===Swift=== |
|||
The ''ternary conditional operator'' of Swift is written in the usual way of the C tradition, and is used within expressions. |
|||
<syntaxhighlight lang="swift"> |
|||
let result = a > b ? a : b |
|||
</syntaxhighlight> |
|||
===Tcl=== |
|||
In [[Tcl]], this operator is available in <code>expr</code> expressions only: |
|||
<syntaxhighlight lang="tcl"> |
|||
set x 5 |
|||
set y [expr {$x == 5 ? 10 : 15}] |
|||
</syntaxhighlight> |
|||
Outside of <code>expr</code>, <code>if</code> can be used for a similar purpose, as it also returns a value: |
|||
<syntaxhighlight lang="tcl"> |
|||
package require math |
|||
set x 5 |
|||
set y [if {$x == 5} { |
|||
::math::random $x |
|||
} else { |
|||
::math::fibonacci $x |
|||
}] |
|||
</syntaxhighlight> |
|||
===TestStand=== |
===TestStand=== |
||
In a [http://www.ni.com/teststand/ National Instruments TestStand] expression, if condition is true, the first expression is evaluated and becomes the output of the |
In a [http://www.ni.com/teststand/ National Instruments TestStand] expression, if condition is true, the first expression is evaluated and becomes the output of the conditional operation; if false, the second expression is evaluated and becomes the result. Only one of two expressions is ever evaluated. |
||
<source lang="c">condition ? first_expression : second_expression</source> |
|||
<syntaxhighlight lang="c"> |
|||
condition ? first_expression : second_expression |
|||
</syntaxhighlight> |
|||
For example: |
For example: |
||
<source lang="c">RunState.Root.Parameters.TestSocket.Index == 3 ? Locals.UUTIndex = 3 : Locals.UUTIndex = 0</source> |
|||
<syntaxhighlight lang="c"> |
|||
Sets the '''UUTIndex''' local variable to 3 if '''TestSocket.Index''' is 3, otherwise it sets '''UUTIndex''' to 0. |
|||
RunState.Root.Parameters.TestSocket.Index == 3 ? Locals.UUTIndex = 3 : Locals.UUTIndex = 0 |
|||
</syntaxhighlight> |
|||
Sets the {{code|UUTIndex}} local variable to 3 if {{code|TestSocket.Index}} is 3, otherwise it sets {{code|UUTIndex}} to 0. |
|||
Similar to other languages, '''first_expression''' and '''second_expression''' do not need to be autonomous expressions, allowing the operator to be used for variable assignment: |
Similar to other languages, '''first_expression''' and '''second_expression''' do not need to be autonomous expressions, allowing the operator to be used for variable assignment: |
||
<source lang="c">Locals.UUTIndex = ( RunState.Root.Parameters.TestSocket.Index == 3 ? 3 : 0 )</source> |
|||
<syntaxhighlight lang="c"> |
|||
Locals.UUTIndex = ( RunState.Root.Parameters.TestSocket.Index == 3 ? 3 : 0 ) |
|||
</syntaxhighlight> |
|||
===Verilog=== |
|||
[[Verilog]] is technically a [[hardware description language]], not a programming language though the semantics of both are very similar. It uses the {{code|?:}} syntax for the ternary operator. |
|||
<syntaxhighlight lang="verilog"> |
|||
// using blocking assignment |
|||
wire out; |
|||
assign out = sel ? a : b; |
|||
</syntaxhighlight> |
|||
This is equivalent to the more verbose Verilog code: |
|||
<syntaxhighlight lang="verilog"> |
|||
// using blocking assignment |
|||
wire out; |
|||
if (sel === 1) // sel is 1, not 0, x or z |
|||
assign out = a; |
|||
else if (sel === 0) // sel is 0, x or z (1 checked above) |
|||
assign out = b; |
|||
else // sel is x or z (0 and 1 checked above) |
|||
assign out = [comment]; // a and b are compared bit by bit, and return for each bit |
|||
// an x if bits are different, and the bit value if the same |
|||
</syntaxhighlight> |
|||
===Visual Basic=== |
===Visual Basic=== |
||
[[Visual Basic]] doesn't use |
[[Visual Basic]] doesn't use {{code|?:}} per se, but has a very similar implementation of this shorthand {{code|if...else}} statement. Using the first example provided in this article, it can do: |
||
< |
<syntaxhighlight lang="vbnet"> |
||
' variable = IIf(condition, value_if_true, value_if_false) |
' variable = IIf(condition, value_if_true, value_if_false) |
||
Dim opening_time As Integer = IIf((day = |
Dim opening_time As Integer = IIf((day = SUNDAY), 12, 9) |
||
</syntaxhighlight> |
|||
</source> |
|||
In the above example, |
In the above example, {{code|IIf}} is a ternary function, but not a ternary operator. As a function, the values of all three portions are evaluated before the function call occurs. This imposed limitations, and in Visual Basic .Net 9.0, released with Visual Studio 2008, an actual conditional operator was introduced, using the {{code|If}} keyword instead of {{code|IIf}}. This allows the following example code to work: |
||
< |
<syntaxhighlight lang="vbnet"> |
||
Dim name As String = If(person Is Nothing, "", person.Name) |
Dim name As String = If(person Is Nothing, "", person.Name) |
||
</syntaxhighlight> |
|||
</source> |
|||
Using |
Using {{code|IIf}}, {{code|person.Name}} would be evaluated even if person is [[null pointer|{{code|null}}]] (Nothing), causing an [[exception handling|exception]]. With a true short-circuiting conditional operator, {{code|person.Name}} is not evaluated unless person is not {{code|null}}. |
||
[[Visual Basic .NET|Visual Basic]] Version 9 has added |
[[Visual Basic .NET|Visual Basic]] Version 9 has added the operator {{code|If()}} in addition to the existing {{code|IIf()}} function that existed previously. As a true operator, it does not have the side effects and potential inefficiencies of the {{code|IIf()}} function. |
||
The syntaxes of the tokens are similar: |
The syntaxes of the tokens are similar: {{code|If([condition], op1, op2)}} vs {{code|IIf(condition, op1, op2)}}. As mentioned above, the function call has significant disadvantages, because the sub-expressions must all be evaluated, according to Visual Basic's [[evaluation strategy]] for function calls and the result will always be of type variant (VB) or object (VB.NET). The {{code|If()}}operator however does not suffer from these problems as it supports conditional evaluation and determines the type of the expression based on the types of its operands. |
||
===Zig=== |
|||
[[Zig (programming language)|Zig]] uses ''if-else'' expressions instead of a ternary conditional operator:<ref>{{Cite web |title=Zig Language Reference |url=https://ziglang.org/documentation/master/#if |access-date=2023-08-09 |website=ziglang.org}}</ref> |
|||
<syntaxhighlight lang="zig"> |
|||
const result = if (a != b) 47 else 3089; |
|||
</syntaxhighlight> |
|||
==Result type== |
==Result type== |
||
Clearly the type of the result of the |
Clearly the type of the result of the {{code|?:}} operator must be in some sense the [[type unification]] of the types of its second and third operands. In C this is accomplished for [[numeric type]]s by [[arithmetic promotion]]; since C does not have a [[type hierarchy]] for [[Pointer (computer programming)|pointer]] types, pointer operands may only be used if they are of the same type (ignoring [[type qualifier]]s) or one is [[void type|void]] or [[Null pointer|NULL]]. It is [[undefined behaviour]] to mix pointer and integral or incompatible pointer types; thus |
||
<source lang="c">number = spell_out_numbers ? "forty-two" : 42;</source> |
|||
<syntaxhighlight lang="c"> |
|||
number = spell_out_numbers ? "forty-two" : 42; |
|||
</syntaxhighlight> |
|||
will result in a [[compile-time error]] in most compilers. |
will result in a [[compile-time error]] in most compilers. |
||
==?: in style guidelines== |
==?: in style guidelines== |
||
Conditional operators are widely used and can be useful in certain circumstances to avoid the use of an {{code|if}} statement, either because the extra verbiage would be too lengthy or because the syntactic context does not permit a statement. For example: |
|||
[[C preprocessor|#define]] MAX(a, b) (((a)>(b)) ? (a) : (b)) |
[[C preprocessor|#define]] MAX(a, b) (((a)>(b)) ? (a) : (b)) |
||
or |
or |
||
<source lang="c"> |
|||
<syntaxhighlight lang="cpp"> |
|||
for (i = 0; i < MAX_PATTERNS; i++) |
for (i = 0; i < MAX_PATTERNS; i++) |
||
c_patterns[i].ShowWindow(m_data.fOn[i] ? SW_SHOW : SW_HIDE); |
c_patterns[i].ShowWindow(m_data.fOn[i] ? SW_SHOW : SW_HIDE); |
||
</syntaxhighlight> |
|||
</source> |
|||
(The latter example uses the [[Microsoft Foundation Classes]] Framework for [[Win32]].) |
(The latter example uses the [[Microsoft Foundation Classes]] Framework for [[Win32]].) |
||
===Initialization=== |
|||
An important use of the conditional operator is in allowing a single initialization statement, rather than multiple initialization statements. In many cases this also allows [[single assignment]] and for an identifier to be a [[constant (computer programming)|constant]]. |
|||
The simplest benefit is avoiding duplicating the variable name, as in Python: |
|||
<syntaxhighlight lang="python"> |
|||
x = 'foo' if b else 'bar' |
|||
</syntaxhighlight> |
|||
instead of: |
|||
<syntaxhighlight lang="python"> |
|||
if b: |
|||
x = 'foo' |
|||
else: |
|||
x = 'bar' |
|||
</syntaxhighlight> |
|||
More importantly, in languages with [[block scope]], such as C++, the blocks of an if/else statement create new scopes, and thus variables must be declared ''before'' the if/else statement, as: |
|||
<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 (formally, of [[const (computer programming)|{{code|const}}]] type): |
|||
<syntaxhighlight lang="cpp"> |
|||
const std::string s = b ? "foo" : "bar"; |
|||
</syntaxhighlight> |
|||
===Case selectors=== |
|||
When properly formatted, the conditional operator can be used to write simple and coherent case selectors. For example: |
When properly formatted, the conditional operator can be used to write simple and coherent case selectors. For example: |
||
<source lang="c"> |
|||
<syntaxhighlight lang="c"> |
|||
vehicle = arg == 'B' ? bus : |
vehicle = arg == 'B' ? bus : |
||
arg == 'A' ? airplane : |
arg == 'A' ? airplane : |
||
Line 457: | Line 1,041: | ||
arg == 'H' ? horse : |
arg == 'H' ? horse : |
||
feet; |
feet; |
||
</syntaxhighlight> |
|||
</source> |
|||
Appropriate use of the conditional operator in a variable assignment context reduces the probability of a bug from a faulty assignment as the assigned variable is stated just once as opposed to multiple times. |
Appropriate use of the conditional operator in a variable assignment context reduces the probability of a bug from a faulty assignment as the assigned variable is stated just once as opposed to multiple times. |
||
== |
==Programming languages without the conditional operator== |
||
The following are examples of notable general-purpose programming languages that don't provide a conditional operator: |
The following are examples of notable general-purpose programming languages that don't provide a conditional operator: |
||
* [[CoffeeScript]] |
|||
* [[Go_(programming_language)|Go]] programming language<ref>{{cite web |url= http://golang.org/doc/go_faq.html#Does_Go_have_a_ternary_form |work= The Go Programming Language FAQ |title= Does Go have the ?: operator? |accessdate= 2012-08-05}}</ref> |
|||
* [[Go (programming language)|Go]] programming language<ref name="go-ternary">{{cite web |url= https://go.dev/doc/faq#Does_Go_have_a_ternary_form |work= The Go Programming Language FAQ |title= Does Go have the ?: operator? |access-date= 2012-08-05}}</ref> (although provided by 3rd-party libraries<ref>{{Cite web |title=lo package - github.com/samber/lo - Go Packages |url=https://pkg.go.dev/github.com/samber/lo#Ternary |access-date=2023-09-30 |website=pkg.go.dev}}</ref>) |
|||
* [[Pascal_(programming_language)|Pascal]] |
|||
* [[MATLAB]] |
|||
* [[Pascal (programming language)|Pascal]] although [[Object Pascal|Object Pascal / Delphi]] do have a function {{code|IfThen}} to do the same (with caveats) |
|||
* [[Rust (programming language)|Rust]] The {{code|if..else}} construct is an expression and can be used to get the same functionality.<ref>{{cite web |url= http://doc.rust-lang.org/reference.html#if-expressions |work= The Rust Reference |title= If expressions |access-date= 2015-07-21}}</ref> |
|||
* [[Scala (programming language)|Scala]] |
|||
* {{ill|XProfan|de|XProfan}} |
|||
* [[PowerShell]] (in old versions) an elegant workaround is to use <code>(''<value for true>'',''<value for false>'')[!(''<condition>'')]</code><ref>{{Cite web|url=https://stackoverflow.com/questions/31341998/ternary-operator-in-powershell|title=Ternary operator in PowerShell|website=Stack Overflow|access-date=2018-10-09}}</ref> |
|||
==See also== |
==See also== |
||
*[[IIf]], inline if function |
* [[IIf]], inline if function |
||
*[[Null coalescing operator]], ?? operator |
* [[Null coalescing operator]], {{code|??}} operator |
||
* [[Elvis operator]], {{code|?:}}, or sometimes {{code|?.}}, as a shorthand [[binary operator]] |
|||
* [[Conditioned disjunction]], equivalent ternary logical connective. |
|||
* [[Multiplexer]] |
|||
== |
==References== |
||
{{reflist|2}} |
{{reflist|2}} |
||
== |
==External links== |
||
* [ |
* [https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/operators/if-operator Description of If operator in Visual Basic] |
||
* [ |
* [https://www.python.org/dev/peps/pep-0308/ Description of Conditional Expression in Python (PEP 308)] |
||
* [ |
* [https://docs.oracle.com/javase/specs/#15.25 Description in the Java Language Specification] |
||
* [https://php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary Description in the PHP Language Documentation] |
|||
* [http://www.diveintopython.net/power_of_introspection/and_or.html Alternative workaround for ternary conditional expression in Python] |
|||
* [http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.25 Description in the Java Language Specification] |
|||
* [http://php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary Description in the PHP Language Documentation] |
|||
* [http://www.microsoft.com/downloads/details.aspx?familyid=39DE1DD0-F775-40BF-A191-09F5A95EF500&displaylang=en Visual Basic 9.0 Language Specification] |
|||
[[Category:Conditional constructs]] |
[[Category:Conditional constructs]] |
||
[[Category:Operators (programming)]] |
|||
[[Category:Ternary operations]] |
[[Category:Ternary operations]] |
||
[[Category:Articles with example code]] |
[[Category:Articles with example code]] |
||
[[de:Bedingte Anweisung und Verzweigung#Auswahloperator]] |
|||
[[cs:Ternární operátor (programování)]] |
|||
[[de:?:]] |
|||
[[ja:条件演算子]] |
|||
[[pl:Operator warunkowy]] |
|||
[[ru:Тернарная условная операция]] |
|||
[[zh:条件运算符]] |
Latest revision as of 15:48, 9 November 2024
In computer programming, the ternary conditional operator is a ternary operator that is part of the syntax for basic conditional expressions in several programming languages. It is commonly referred to as the conditional operator, conditional expression, ternary if, or inline if (abbreviated iif). An expression if a then b else c
or a ? b : c
evaluates to b
if the value of a
is true, and otherwise to c
. One can read it aloud as "if a then b otherwise c". The form a ? b : c
is the most common, but alternative syntax do exist; for example, Raku uses the syntax a ?? b !! c
to avoid confusion with the infix operators ?
and !
, whereas in Visual Basic .NET, it instead takes the form If(a, b, c)
.
It originally comes from CPL, in which equivalent syntax for e1 ? e2 : e3
was e1 → e2, e3
.[1][2]
Although many ternary operators are possible, the conditional operator is so common, and other ternary operators so rare, that the conditional operator is commonly referred to as the ternary operator.
Variations
[edit]The detailed semantics of "the" ternary operator as well as its syntax differs significantly from language to language.
A top level distinction from one language to another is whether the expressions permit side effects (as in most procedural languages) and whether the language provides short-circuit evaluation semantics, whereby only the selected expression is evaluated (most standard operators in most languages evaluate all arguments).
If the language supports expressions with side effects but does not specify short-circuit evaluation, then a further distinction exists about which expression evaluates first—if the language guarantees any specific order (bear in mind that the conditional also counts as an expression).
Furthermore, 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 the language does not permit side-effects in expressions (common in functional languages), then the order of evaluation has no value semantics—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 variable = condition ? expr1 : expr2;
can have subtly different semantics than the block conditional form if (condition) { variable = expr1; } else { variable = expr2; }
(in the C language—the syntax of the example given—these are in fact equivalent).
The associativity of nested ternary operators can also differ from language to language. In almost all languages, the ternary operator is right associative so that a == 1 ? "one" : a == 2 ? "two" : "many"
evaluates intuitively as a == 1 ? "one" : (a == 2 ? "two" : "many")
, but PHP in particular is notoriously left-associative,[3] and evaluates as follows: (a == 1 ? "one" : a == 2) ? "two" : "many"
, which is rarely what any programmer expects. (The given examples assume that the ternary operator has low operator precedence, which is true in all C-family languages, and many others.)
Equivalence to map
[edit]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 c(expr1,expr2)[1+condition]
(this idiom is slightly more natural in languages with 0-origin subscripts).
Nested ternaries can be simulated as c(expr1,expr2,expr3)[which.first((c(cond1,cond2,TRUE))]
where the function which.first
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.
Conditional assignment
[edit]Originally from ALGOL 60 the conditional assignment of ALGOL is:
variable := if condition then expression_1 else expression_2;
?:
is used as follows:
condition ? value_if_true : value_if_false
The condition is evaluated true or false as a Boolean expression. On the basis of the evaluation of the Boolean condition, the entire expression returns value_if_true if condition is true, but value_if_false otherwise. Usually the two sub-expressions value_if_true and value_if_false must have the same type, which determines the type of the whole expression. The importance of this type-checking lies in the operator's most common use—in conditional assignment statements. In this usage it appears as an expression on the right side of an assignment statement, as follows:
variable = condition ? value_if_true : value_if_false
The ?: operator is similar to the way conditional expressions (if-then-else constructs) 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.
Usage
[edit]The conditional operator's most common usage is to make a terse simple conditional assignment statement. For example, if we wish to implement some C code to change a shop's normal opening hours from 9 o'clock to 12 o'clock on Sundays, we may use
int opening_time = (day == SUNDAY) ? 12 : 9;
instead of the more verbose
int opening_time;
if (day == SUNDAY)
opening_time = 12;
else
opening_time = 9;
The two forms are nearly equivalent. Keep in mind that the ?:
is an expression and if-then-else is a statement. Note that neither the true nor false portions can be omitted from the conditional operator without an error report upon parsing. This contrasts with if-then-else statements, where the else clause can be omitted.
Most of the languages emphasizing functional programming don't need such an operator as their regular conditional expression(s) is an expression in the first place e.g. the Scheme expression (if (> a b) a b)
is equivalent in semantics to the C expression (a > b) ? a : b
. This is also the case in many imperative languages, starting with ALGOL where it is possible to write result := if a > b then a else b
, or Smalltalk (result := (a > b) ifTrue: [ a ] ifFalse: [ b ]
) or Ruby (result = if a > b then a else b end
, although result = a > b ? a : b
works as well).
Note that some languages may evaluate both the true- and false-expressions, even though only one or the other will be assigned to the variable. This means that if the true- or false-expression contain a function call, that function may be called and executed (causing any related side-effects due to the function's execution), regardless of whether or not its result will be used. Programmers should consult their programming language specifications or test the ternary operator to determine whether or not the language will evaluate both expressions in this way. If it does, and this is not the desired behaviour, then an if-then-else statement should be used.
ActionScript 3
[edit]condition ? value_if_true : value_if_false
Ada
[edit]The 2012 edition of Ada has introduced conditional expressions (using if
and case
), as part of an enlarged set of expressions including quantified expressions and expression functions. The Rationale for Ada 2012[4] states motives for Ada not having had them before, as well as motives for now adding them, such as to support "contracts" (also new).
Pay_per_Hour := (if Day = Sunday
then 12.50
else 10.00);
When the value of an if_expression is itself of Boolean type, then the else
part may be omitted, the value being True. Multiple conditions may chained using elsif
.
ALGOL 60
[edit]ALGOL 60 introduced conditional expressions (thus ternary conditionals) to imperative programming languages.
if <boolean expression> then <expression> else <expression>
Rather than a conditional statement:
integer opening_time;
if day = Sunday then
opening_time := 12;
else
opening_time := 9;
the programmer could use the conditional expression to write more succinctly:
integer opening_time;
opening_time := if day = Sunday then 12 else 9;
ALGOL 68
[edit]Both ALGOL 68's choice clauses (if and the case clauses) provide the coder with a choice of either the "bold" syntax or the "brief" form.
- Single if choice clause:
if condition then statements [ else statements ] fi
- "brief" form:
( condition | statements | statements )
- "brief" form:
- Chained if choice clause:
if condition1 then statements elif condition2 then statements [ else statements ] fi
- "brief" form:
( condition1 | statements |: condition2 | statements | statements )
- "brief" form:
APL
[edit]With the following syntax, both expressions are evaluated (with value_if_false
evaluated first, then condition
, then value_if_false
):
result ← value_if_true ⊣⍣ condition ⊢ value_if_false
This alternative syntax provides short-circuit evaluation:
result ← { condition : expression_if_true ⋄ expression_if_false } ⍬
AWK
[edit]result = condition ? value_if_true : value_if_false
Bash
[edit]A true ternary operator only exists for arithmetic expressions:
((result = condition ? value_if_true : value_if_false))
For strings there only exist workarounds, like e.g.:
result=$([[ "$a" = "$b" ]] && echo "value_if_true" || echo "value_if_false")
Where "$a" = "$b"
can be any condition [[ … ]]
construct can evaluate. Instead of the [[ … ]]
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
[edit]A traditional if-else construct in C is written:
if (a > b) {
result = x;
}
else {
result = y;
}
This can be rewritten as the following statement:
result = a > b ? x : y;
As in the if-else construct only one of the expressions 'x' and 'y' is evaluated. This is significant if the evaluation of 'x' or 'y' has side effects.[5] The behaviour is undefined if an attempt is made to use the result of the conditional operator as an lvalue.[5]
A GNU extension to C allows omitting the second operand, and using implicitly the first operand as the second also:
a = x ? : y;
The expression is equivalent to
a = x ? x : y;
except that expressions a and x are evaluated only once. The difference is significant if evaluating the expression has side effects. This shorthand form is sometimes known as the Elvis operator in other languages.
C#
[edit]In C#, if condition is true, first expression is evaluated and becomes the result; if false, the second expression is evaluated and becomes the result. As with Java only one of two expressions is ever evaluated.
// condition ? first_expression : second_expression;
static double sinc(double x)
{
return x != 0.0 ? Math.Sin(x) / x : 1.0;
}
C++
[edit]Unlike in C, the precedence of the ?:
operator in C++ is the same as that of the assignment operator (=
or OP=
), and it can return an lvalue.[6] This means that expressions like q ? a : b = c
and (q ? a : b) = c
are both legal and are parsed differently, the former being equivalent to q ? a : (b = c)
.
In C++ there are conditional assignment situations where use of the if-else statement is impossible, since this language explicitly distinguishes between initialization and assignment. In such case it is always possible to use a function call, but this can be cumbersome and inelegant. For example, to pass conditionally different values as an argument for a constructor of a field or a base class, it is impossible to use a plain if-else statement; in this case we can use a conditional assignment expression, or a function call. Bear in mind also that some types allow initialization, but do not allow assignment, or even that the assignment operator and the constructor do totally different things. This last is true for reference types, for example:
#include <iostream>
#include <fstream>
#include <string>
int main(int argc, char *argv[])
{
std::string name;
std::ofstream fout;
if (argc > 1 && argv[1])
{
name = argv[1];
fout.open(name.c_str(), std::ios::out | std::ios::app);
}
std::ostream &sout = name.empty() ? std::cout : fout;
sout << "Hello, world!\n";
return 0;
}
In this case, using an if-else statement in place of the ?:
operator forces the target of the assignment to be declared outside of the branches as a pointer, which can be freely rebound to different objects.
std::ostream* sout = &fout;
if (name.empty()) {
sout = &std::cout;
}
*sout << "Hello, world!\n";
In this simple example, the sout
pointer can be initialized to a default value, mitigating the risk of leaving pointers uninitialized or null. Nevertheless, there are cases when no good default exists or creating a default value is expensive. More generally speaking, keeping track of a nullable pointer increases cognitive load. Therefore, only conditional assignment to a reference through the ?:
operator conveys the semantics of Initializing a variable from only one of two choices based on a predicate appropriately.
Furthermore, the conditional operator can yield an lvalue, i.e. a value to which another value can be assigned. Consider the following example:
#include <iostream>
int main(int argc, char *argv[])
{
int a = 0;
int b = 0;
(argc > 1 ? a : b) = 1;
std::cout << "a: " << a
<< " b: " << b
<< '\n';
return 0;
}
In this example, if the boolean expression argc > 1
yields the value true
on line 8, the value 1
is assigned to the variable a
, otherwise the value 1
is assigned to the variable b
.
CFML
[edit]Example of the ?:
operator in CFML:
result = randRange(0,1) ? "heads" : "tails";
Roughly 50% of the time the randRange()
expression will return 1 (true) or 0 (false); meaning result will take the value "heads" or "tails" respectively.
Lucee, Railo, and ColdFusion 11-specific
[edit]Lucee, Railo, and ColdFusion 11 also implement the Elvis operator, ?:
which will return the value of the expression if it is not-null, otherwise the specified default.
Syntax:
result = expression ?: value_if_expression_is_null
Example:
result = f() ?: "default";
// where...
function f(){
if (randRange(0,1)){ // either 0 or 1 (false / true)
return "value";
}
}
writeOutput(result);
The function f()
will return value
roughly 50% of the time, otherwise will not return anything. If f()
returns "value", result
will take that value, otherwise will take the value "default".
CoffeeScript
[edit]Example of using this operator in CoffeeScript:
if 1 is 2 then "true value" else "false value"
Returns "false value".
Common Lisp
[edit]Assignment using a conditional expression in Common Lisp:
(setq result (if (> a b) x y))
Alternative form:
(if (> a b)
(setq result x)
(setq result y))
Crystal
[edit]Example of using this operator in Crystal:
1 == 2 ? "true value" : "false value"
Returns "false value"
.
The Crystal compiler transforms conditional operators to if
expressions, so the above is semantically identical to:
if 1 == 2
"true value"
else
"false value"
end
Dart
[edit]The Dart programming language's syntax belongs to the C family, primarily inspired by languages like Java, C# and JavaScript, which means it has inherited the traditional ?:
syntax for its conditional expression.
Example:
return x.isEven ? x ~/ 2 : x * 3 + 1;
Like other conditions in Dart, the expression before the ?
must evaluate to a Boolean value.
The Dart syntax uses both ?
and :
in various other ways, which causes ambiguities in the language grammar. An expression like:
{ x as T ? [1] : [2] }
could be parsed as either a "set literal" containing one of two lists or as a "map literal" {((x as T?)[1]) : [2]}
. The language always chooses the conditional expression in such situations.
Dart also has a second ternary operator, the []=
operator commonly used for setting values in lists or maps, which makes the term "the ternary operator" ambiguous in a Dart context.
Delphi
[edit]In Delphi the IfThen
function can be used to achieve the same as ?:
. If the System.Math
library is used, the IfThen
function returns a numeric value such as an Integer, Double or Extended. If the System.StrUtils
library is used, this function can also return a string value.
Using System.Math
function IfThen(AValue: Boolean; const ATrue: Integer; const AFalse: Integer): Integer;
function IfThen(AValue: Boolean; const ATrue: Int64; const AFalse: Int64): Int64;
function IfThen(AValue: Boolean; const ATrue: UInt64; const AFalse: UInt64): UInt64;
function IfThen(AValue: Boolean; const ATrue: Single; const AFalse: Single): Single;
function IfThen(AValue: Boolean; const ATrue: Double; const AFalse: Double): Double;
function IfThen(AValue: Boolean; const ATrue: Extended; const AFalse: Extended): Extended;
Using the System.StrUtils
library
function IfThen(AValue: Boolean; const ATrue: string; AFalse: string = ''): string;
Usage example:
function GetOpeningTime(Weekday: Integer): Integer;
begin
{ This function will return the opening time for the given weekday: 12 for Sundays, 9 for other days }
Result := IfThen((Weekday = 1) or (Weekday = 7), 12, 9);
end;
Unlike a true ternary operator however, both of the results are evaluated prior to performing the comparison. For example, if one of the results is a call to a function which inserts a row into a database table, that function will be called whether or not the condition to return that specific result is met.
Eiffel
[edit]The original Eiffel pure OO language from 1986 did not have conditional expressions. Extensions to Eiffel to integrate the style and benefits of functional in the form of agents (closely associated with functional lambdas) were proposed and implemented in 2014.
if <boolean expression> then <expression> else <expression>
opening_time: INTEGER
opening_time := if day = Sunday then 12 else 9
F#
[edit]In F# the built-in syntax for if-then-else is already an expression that always must return a value.
let num = if x = 10 then 42 else 24
F# has a special case where you can omit the else branch if the return value is of type unit. This way you can do side-effects, without using an else branch.
if x = 10 then
printfn "It is 10"
But even in this case, the if expression would return unit. You don't need to write the else branch, because the compiler will assume the unit type on else.
FORTH
[edit]Since FORTH is a stack-oriented language, and any expression can leave a value on the stack, all IF
/ELSE
/THEN
sequences can generate values:
: test ( n -- n ) 1 AND IF 22 ELSE 42 THEN ;
This word takes 1 parameter on the stack, and if that number is odd, leaves 22. If it's even, 42 is left on the stack.
Fortran
[edit]With the additions to the code in the 1995 release, the ternary operator was added to the Fortran compiler as the intrinsic function merge
:
variable = merge(x,y,a>b)
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.
FreeMarker
[edit]This built-in exists since FreeMarker 2.3.20.
Used like booleanExp?then(whenTrue, whenFalse)
, fills the same role as the ternary operator in C-like languages.
<#assign x = 10>
<#assign y = 20>
<#-- Prints the maximum of x and y: -->
${(x > y)?then(x, y)}
Go
[edit]There is no ternary if in Go, so use of the full if statement is always required.[7]
Haskell
[edit]The built-in if-then-else syntax is inline: the expression
if predicate then expr1 else expr2
has type
Bool -> a -> a -> a
The base library also provides the function Data.Bool.bool
:
bool :: a -> a -> Bool -> a
In both cases, no special treatment is needed to ensure that only the selected expression is evaluated, since Haskell is non-strict by default. This also means an operator can be defined that, when used in combination with the $
operator, functions exactly like ?:
in most languages:
(?) :: Bool -> a -> a -> a
(?) pred x y = if pred then x else y
infix 1 ?
-- example (vehicle will evaluate to "airplane"):
arg = 'A'
vehicle = arg == 'B' ? "boat" $
arg == 'A' ? "airplane" $
arg == 'T' ? "train" $
"car"
However, it is more idiomatic to use pattern guards
-- example (vehicle will evaluate to "airplane"):
arg = 'A'
vehicle | arg == 'B' = "boat"
| arg == 'A' = "airplane"
| arg == 'T' = "train"
| otherwise = "car"
Java
[edit]In Java this expression evaluates to:
// If foo is selected, assign selected foo to bar. If not, assign baz to bar.
Object bar = foo.isSelected() ? foo : baz;
Note that Java, in a manner similar to C#, only evaluates the used expression and will not evaluate the unused expression.[8]
Julia
[edit]In Julia, "Note that the spaces around ?
and :
are mandatory: an expression like a?b:c
is not a valid ternary expression (but a newline is acceptable after both the ?
and the :
)."[9]
JavaScript
[edit]The conditional operator in JavaScript is similar to that of C++ and Java, except for the fact the middle expression cannot be a comma expression. Also, as in C++, but unlike in C or Perl, it will not bind tighter than an assignment to its right—q ? a : b = c
is equivalent to q ? a : (b = c)
instead of (q ? a : b) = c
.[10]
var timeout = settings === null ? 1000 : settings.timeout;
Just like C# and Java, the expression will only be evaluated if, and only if, the expression is the matching one for the condition given; the other expression will not be evaluated.
Lisp
[edit]As the first functional programming language, Lisp naturally has conditional expressions since there are no statements and thus not conditional statements. The form is:
(if test-expression then-expression else-expression)
Hence:
(if day = Sunday 12 9)
Kotlin
[edit]Kotlin does not include the traditional ?:
ternary operator, however, if
s can be used as expressions that can be assigned,[11] achieving the same results. Note that, as the complexity of one's conditional statement grows, the programmer might consider replacing their if
-else
expression with a when
expression.
val max = if (a > b) a else b
Lua
[edit]Lua does not have a traditional conditional operator. However, the short-circuiting behaviour of its and
and or
operators allows the emulation of this behaviour:
-- equivalent to var = cond ? a : b;
var = cond and a or b
This will succeed unless a
is logically false (i.e. false
or nil
); in this case, the expression will always result in b
. This can result in some surprising behaviour if ignored.
There are also other variants that can be used, but they're generally more verbose:
-- parentheses around the table literal are required
var = (
{
[true] = a,
[false] = b
}
)[not not cond]
Luau, a dialect of Lua, has ternary expressions that look like if statements, but unlike them, they have no end
keyword, and the else
clause is required. One may optionally add elseif
clauses. It's designed to replace the cond and a or b
idiom and is expected to work properly in all cases.[12]
-- 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
Objective-C
[edit]condition ? value_if_true : value_if_false
int min = (1 < 2) ? 1 : 2;
This will set the variable min
to 1
because the condition (1 < 2)
is true
.
Pascal
[edit]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.
Perl
[edit]A traditional if-else construct in Perl is written:
if ($a > $b) {
$result = $x;
} else {
$result = $y;
}
Rewritten to use the conditional operator:
$result = $a > $b ? $x : $y;
The precedence of the conditional operator in Perl is the same as in C, not as in C++. This is conveniently of higher precedence than a comma operator but lower than the precedence of most operators used in expressions within the ternary operator, so the use of parentheses is rarely required.[13]
Its associativity matches that of C and C++, not that of PHP. Unlike C but like C++, Perl allows the use of the conditional expression as an L-value;[14] for example:
$a > $b ? $x : $y = $result;
will assign $result
to either $x
or $y
depending on the logical expression's boolean result.
The respective precedence rules and associativities of the operators used guarantee that the version absent any parentheses is equivalent to this explicitly parenthesized version:
(($a > $b) ? $x : $y) = $result;
This is equivalent to the if-else version:
if ($a > $b) {
$x = $result;
} else {
$y = $result;
}
PHP
[edit]A simple PHP implementation is this:
$abs = $value >= 0 ? $value : -$value;
Unlike most other programming languages, the conditional operator in PHP is left associative rather than right associative. Thus, given a value of T for arg, the PHP code in the following example would yield the value horse instead of train as one might expect:[15]
<?php
$arg = "T";
$vehicle = ( ( $arg == 'B' ) ? 'bus' :
( $arg == 'A' ) ? 'airplane' :
( $arg == 'T' ) ? 'train' :
( $arg == 'C' ) ? 'car' :
( $arg == 'H' ) ? 'horse' :
'feet' );
echo $vehicle;
The reason is that nesting two conditional operators produces an oversized condition with the last two options as its branches: c1 ? o1 : c2 ? o2 : o3
is really ((c1 ? o1 : c2) ? o2 : o3)
. This is acknowledged[16] and will probably not change.[17] To avoid this, nested parenthesis are needed, as in this example:
<?php
$arg = "T";
$vehicle = $arg == "B" ? "bus" :
($arg == "A" ? "airplane" :
($arg == "T" ? "train" :
($arg == "C" ? "car" :
($arg == "H" ? "horse" :
"feet"))));
echo $vehicle;
This will produce the result of train being printed to the output, analogous to a right associative conditional operator.
Powershell
[edit]In versions before Powershell 7 ternary operators are not supported [18] however conditional syntax does support single line assignment:
$result = if $a -eq $b {"was true" } else {"was false"}
In Powershell 7+ traditional ternary operators are supported and follow the C# syntax:[19]
$result = $a -eq $b ? "was true" : "was false"
Python
[edit]Though it had been delayed for several years by disagreements over syntax, 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 ?:
operator in the order of its operands. The general form is:[20]
result = x if a > b else y
This form invites considering x
as the normal value and y
as an exceptional case.
Prior to Python 2.5 there were a number of ways to approximate a conditional operator (for example by indexing into a two element array), all of which have drawbacks as compared to the built-in operator.
R
[edit]The traditional if-else construct in R (which is an implementation of S) is:
if (a < b) {
x <- "true"
} else {
x <- "false"
}
If there is only one statement in each block, braces can be omitted, like in C:
if (a < b)
x <- "true"
else
x <- "false"
The code above can be written in the following non-standard condensed way:
x <- if (a < b) "true" else "false"
There exists also the function ifelse
that allows rewriting the expression above as:
x <- ifelse(a < b, "true", "false")
The ifelse
function is automatically vectorized. For instance:
> ifelse(c (0, 2) < 1, "true", "false")
[1] "true" "false"
Raku
[edit]Raku uses a doubled ??
symbol instead of single ?
and a doubled !!
symbol instead of :
[21]
$result = $a > $b ?? $x !! $y;
Ruby
[edit]Example of using this operator in Ruby:
1 == 2 ? "true value" : "false value"
Returns "false value".
A traditional if-else construct in Ruby is written:[22]
if a > b
result = x
else
result = y
end
This could also be written as:
result = if a > b
x
else
y
end
These can be rewritten as the following statement:
result = a > b ? x : y
Rust
[edit]Being an expression-oriented programming language, Rust's existing if expr1 else expr2
syntax can behave as the traditional ?:
ternary operator does. Earlier versions of the language did have the ?:
operator but it was removed[23] due to duplication with if
.[24]
Note the lack of semi-colons in the code below compared to a more declarative if
...else
block, and the semi-colon at the end of the assignment to y
.
let x = 5;
let y = if x == 5 {
10
} else {
15
};
This could also be written as:
let y = if x == 5 { 10 } else { 15 };
Note that curly braces are mandatory in Rust conditional expressions.
You could also use a match
expression:
let y = match x {
5 => 10,
_ => 15,
};
Scheme
[edit]Same as in Common Lisp. Every expression has a value. Thus the builtin if
can be used:
(let* ((x 5)
(y (if (= x 5) 10 15)))
...)
Smalltalk
[edit]Every expression (message send) has a value. Thus ifTrue:ifFalse:
can be used:
|x y|
x := 5.
y := (x == 5) ifTrue:[10] ifFalse:[15].
SQL
[edit]The SQL CASE
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:
SELECT (CASE WHEN a > b THEN x ELSE y END) AS CONDITIONAL_EXAMPLE
FROM tab;
This can be expanded to several conditionals:
SELECT (CASE WHEN a > b THEN x WHEN a < b THEN y ELSE z END) AS CONDITIONAL_EXAMPLE
FROM tab;
MySQL
[edit]In addition to the standard CASE
expression, MySQL provides an IF
function as an extension:
IF(cond, a, b);
SQL Server
[edit]In addition to the standard CASE
expression, SQL Server (from 2012) provides an IIF
function:
IIF(condition, true_value, false_value)
Oracle SQL
[edit]In addition to the standard CASE
expression, Oracle has a variadic functional counterpart which operates similarly to a switch statement and can be used to emulate the conditional operator when testing for equality.
-- General syntax takes case-result pairs, comparing against an expression, followed by a fall-back result:
DECODE(expression, case1, result1,
...
caseN, resultN,
resultElse)
-- We can emulate the conditional operator by just selecting one case:
DECODE(expression, condition, true, false)
The DECODE
function is, today, deprecated in favour of the standard CASE
expression. This can be used in both Oracle SQL queries as well as PL/SQL blocks, whereas decode
can only be used in the former.
Swift
[edit]The ternary conditional operator of Swift is written in the usual way of the C tradition, and is used within expressions.
let result = a > b ? a : b
Tcl
[edit]In Tcl, this operator is available in expr
expressions only:
set x 5
set y [expr {$x == 5 ? 10 : 15}]
Outside of expr
, if
can be used for a similar purpose, as it also returns a value:
package require math
set x 5
set y [if {$x == 5} {
::math::random $x
} else {
::math::fibonacci $x
}]
TestStand
[edit]In a National Instruments TestStand expression, if condition is true, the first expression is evaluated and becomes the output of the conditional operation; if false, the second expression is evaluated and becomes the result. Only one of two expressions is ever evaluated.
condition ? first_expression : second_expression
For example:
RunState.Root.Parameters.TestSocket.Index == 3 ? Locals.UUTIndex = 3 : Locals.UUTIndex = 0
Sets the UUTIndex
local variable to 3 if TestSocket.Index
is 3, otherwise it sets UUTIndex
to 0.
Similar to other languages, first_expression and second_expression do not need to be autonomous expressions, allowing the operator to be used for variable assignment:
Locals.UUTIndex = ( RunState.Root.Parameters.TestSocket.Index == 3 ? 3 : 0 )
Verilog
[edit]Verilog is technically a hardware description language, not a programming language though the semantics of both are very similar. It uses the ?:
syntax for the ternary operator.
// using blocking assignment
wire out;
assign out = sel ? a : b;
This is equivalent to the more verbose Verilog code:
// using blocking assignment
wire out;
if (sel === 1) // sel is 1, not 0, x or z
assign out = a;
else if (sel === 0) // sel is 0, x or z (1 checked above)
assign out = b;
else // sel is x or z (0 and 1 checked above)
assign out = [comment]; // a and b are compared bit by bit, and return for each bit
// an x if bits are different, and the bit value if the same
Visual Basic
[edit]Visual Basic doesn't use ?:
per se, but has a very similar implementation of this shorthand if...else
statement. Using the first example provided in this article, it can do:
' variable = IIf(condition, value_if_true, value_if_false)
Dim opening_time As Integer = IIf((day = SUNDAY), 12, 9)
In the above example, IIf
is a ternary function, but not a ternary operator. As a function, the values of all three portions are evaluated before the function call occurs. This imposed limitations, and in Visual Basic .Net 9.0, released with Visual Studio 2008, an actual conditional operator was introduced, using the If
keyword instead of IIf
. This allows the following example code to work:
Dim name As String = If(person Is Nothing, "", person.Name)
Using IIf
, person.Name
would be evaluated even if person is null
(Nothing), causing an exception. With a true short-circuiting conditional operator, person.Name
is not evaluated unless person is not null
.
Visual Basic Version 9 has added the operator If()
in addition to the existing IIf()
function that existed previously. As a true operator, it does not have the side effects and potential inefficiencies of the IIf()
function.
The syntaxes of the tokens are similar: If([condition], op1, op2)
vs IIf(condition, op1, op2)
. As mentioned above, the function call has significant disadvantages, because the sub-expressions must all be evaluated, according to Visual Basic's evaluation strategy for function calls and the result will always be of type variant (VB) or object (VB.NET). The If()
operator however does not suffer from these problems as it supports conditional evaluation and determines the type of the expression based on the types of its operands.
Zig
[edit]Zig uses if-else expressions instead of a ternary conditional operator:[25]
const result = if (a != b) 47 else 3089;
Result type
[edit]Clearly the type of the result of the ?:
operator must be in some sense the type unification of the types of its second and third operands. In C this is accomplished for numeric types by arithmetic promotion; since C does not have a type hierarchy for pointer types, pointer operands may only be used if they are of the same type (ignoring type qualifiers) or one is void or NULL. It is undefined behaviour to mix pointer and integral or incompatible pointer types; thus
number = spell_out_numbers ? "forty-two" : 42;
will result in a compile-time error in most compilers.
?: in style guidelines
[edit]Conditional operators are widely used and can be useful in certain circumstances to avoid the use of an if
statement, either because the extra verbiage would be too lengthy or because the syntactic context does not permit a statement. For example:
#define MAX(a, b) (((a)>(b)) ? (a) : (b))
or
for (i = 0; i < MAX_PATTERNS; i++)
c_patterns[i].ShowWindow(m_data.fOn[i] ? SW_SHOW : SW_HIDE);
(The latter example uses the Microsoft Foundation Classes Framework for Win32.)
Initialization
[edit]An important use of the conditional operator is in allowing a single initialization statement, rather than multiple initialization statements. In many cases this also allows single assignment and for an identifier to be a constant.
The simplest benefit is avoiding duplicating the variable name, as in Python:
x = 'foo' if b else 'bar'
instead of:
if b:
x = 'foo'
else:
x = 'bar'
More importantly, in languages with block scope, such as C++, the blocks of an if/else statement create new scopes, and thus variables must be declared before the if/else statement, as:
std::string s;
if (b)
s = "foo";
else
s = "bar";
Use of the conditional operator simplifies this:
std::string s = b ? "foo" : "bar";
Furthermore, since initialization is now part of the declaration, rather than a separate statement, the identifier can be a constant (formally, of const
type):
const std::string s = b ? "foo" : "bar";
Case selectors
[edit]When properly formatted, the conditional operator can be used to write simple and coherent case selectors. For example:
vehicle = arg == 'B' ? bus :
arg == 'A' ? airplane :
arg == 'T' ? train :
arg == 'C' ? car :
arg == 'H' ? horse :
feet;
Appropriate use of the conditional operator in a variable assignment context reduces the probability of a bug from a faulty assignment as the assigned variable is stated just once as opposed to multiple times.
Programming languages without the conditional operator
[edit]The following are examples of notable general-purpose programming languages that don't provide a conditional operator:
- CoffeeScript
- Go programming language[7] (although provided by 3rd-party libraries[26])
- MATLAB
- Pascal although Object Pascal / Delphi do have a function
IfThen
to do the same (with caveats) - Rust The
if..else
construct is an expression and can be used to get the same functionality.[27] - Scala
- XProfan
- PowerShell (in old versions) an elegant workaround is to use
(<value for true>,<value for false>)[!(<condition>)]
[28]
See also
[edit]- IIf, inline if function
- Null coalescing operator,
??
operator - Elvis operator,
?:
, or sometimes?.
, as a shorthand binary operator - Conditioned disjunction, equivalent ternary logical connective.
- Multiplexer
References
[edit]- ^ Strachey, Christopher (2000). "Fundamental Concepts in Programming Languages". Higher-Order and Symbolic Computation. 13: 11–49. doi:10.1023/A:1010000313106. S2CID 14124601.
- ^ "5.5 Conditional expressions". The BCPL Reference Manual (PDF). 1967. pp. 16–17. Archived from the original (PDF) on 2016-03-16. Retrieved 2017-03-15.
- ^ Wastl, Eric. "Ternary operator associativity". phpsadness.com. PHP Sadness. Retrieved 20 September 2017.
- ^ "Rationale for Ada 2012". ACAA. Retrieved 10 December 2015.
- ^ a b ISO.IEC 9899:1999 (E) 6.5.15.4
- ^ "C++ Operator Precedence". en.cppreference.com. section: "Notes".
- ^ a b "Does Go have the ?: operator?". The Go Programming Language FAQ. Retrieved 2012-08-05.
- ^ Java 7 Specification: 15.25 Conditional Operator ? :
- ^ "Control Flow · The Julia Language". docs.julialang.org. Retrieved 2020-03-12.
- ^ "ECMA-262 Edition 5.1". Ecma Language Specification. Ecma International. Retrieved 7 September 2013.
- ^ "Kotlin Lang If Expression". kotlinlang.org. Retrieved 2021-04-25.
- ^ "Syntax § If-then-else expressions". Luau. Retrieved 2023-02-07.
- ^ Christiansen, Tom; Wall, Larry; Foy, Brian D (February 2012). "Chapter 2 Unary and Binary Operators: Conditional Operator". Programming Perl (Fourth ed.). Sebastopol, CA: O'Reilly Media. p. 123. ISBN 978-0-596-00492-7.
- ^ Wall, Larry. "perlop: Conditional Operator". Perl Programming Documentation. Retrieved 26 January 2019.
- ^ Eevee (2012-04-09). "PHP: a fractal of bad design". Retrieved 2015-10-04.
- ^ "Comparison Operators, Example #3: Non-obvious Ternary Behaviour". PHP website. Retrieved 2013-04-26.
- ^ "PHP Bug #61915: incorrect associativity of ternary operator". PHP website. 2012-05-02. Retrieved 2013-04-26.
We can't fix this without breaking code
- ^ "about_If - Using the ternary operator syntax". 7 June 2023.
- ^ "about_Operators - Ternary operator". 3 September 2024.
- ^ "The Python Language Reference".
- ^ Wall, Larry. "Perl6 Operators". Archived from the original on 2009-03-29. Retrieved 2010-05-18.
- ^ Programming Ruby: Conditional Execution
- ^ "Remove Ternary Operator by pwoolcoc · Pull Request #1705 · rust-lang/Rust". GitHub.
- ^ "Remove ternary operator · Issue #1698 · rust-lang/Rust". GitHub.
- ^ "Zig Language Reference". ziglang.org. Retrieved 2023-08-09.
- ^ "lo package - github.com/samber/lo - Go Packages". pkg.go.dev. Retrieved 2023-09-30.
- ^ "If expressions". The Rust Reference. Retrieved 2015-07-21.
- ^ "Ternary operator in PowerShell". Stack Overflow. Retrieved 2018-10-09.