Content deleted Content added
m Add a citation to the Python manual |
CortexFiend (talk | contribs) Link suggestions feature: 3 links added. |
||
(58 intermediate revisions by 33 users not shown) | |||
Line 2:
{{Redirect|?:|use as a binary operator|Elvis operator}}
{{mergefrom|conditional operator|discuss=Talk:Conditional operator#Related Article|date=February 2025}}
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 syntaxes 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|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>
Line 19 ⟶ 21:
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.)
Line 26 ⟶ 28:
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==
Originally from ALGOL 60 the conditional assignment of ALGOL is:
''variable'' := '''if''' ''condition'' '''then''' ''expression_1'' '''else''' ''expression_2'';
{{code|?:}} is used 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:
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]],
==Usage==
The conditional operator's most common usage is to
<syntaxhighlight lang="c">
Line 81 ⟶ 87:
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===
Line 87 ⟶ 118:
* Single '''if''' choice clause:
'''if''' condition '''then''' statements [ '''else''' statements ] '''fi'''
* Chained '''if''' choice clause:
'''if''' condition1 '''then''' statements '''elif''' condition2 '''then''' statements [ '''else''' statements ] '''fi'''
===APL===
Line 149 ⟶ 180:
<syntaxhighlight lang="c">
a
</syntaxhighlight>
Line 155 ⟶ 186:
<syntaxhighlight lang="c">
a
</syntaxhighlight>
except that
===C#===
Line 201 ⟶ 232:
</syntaxhighlight>
In this case
<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.
Furthermore, the conditional operator can yield an lvalue, i.e. a value to which another value can be assigned. Consider the following example:
Line 224 ⟶ 265:
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===
Line 357 ⟶ 396:
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 [[
<syntaxhighlight lang="fsharp">
Line 366 ⟶ 417:
</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
<syntaxhighlight lang="fsharp">
Line 373 ⟶ 424:
</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===
Line 385 ⟶ 436:
===Fortran===
<syntaxhighlight lang="fortran">
Line 392 ⟶ 443:
Note that both x and y are evaluated before the results of one or the other are returned from the function. Here, x is returned if the condition holds true and y otherwise.
Fortran-2023 has added conditional expressions which evaluate one or the other of the expressions based on the conditional expression:
<syntaxhighlight lang="fortran">
variable = ( a > b ? x : y )
</syntaxhighlight>
=== FreeMarker ===
Line 464 ⟶ 521:
===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===
Line 474 ⟶ 531:
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 ===
Line 490 ⟶ 557:
</syntaxhighlight>
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:
<syntaxhighlight lang="lua">
-- parentheses around the table literal are required
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>
<syntaxhighlight lang="lua">
-- in Luau
var = if cond then a else b
-- with elseif clause
sign = if var < 0 then -1 elseif var == 0 then 0 else 1
</syntaxhighlight>
=== Objective-C ===
Line 501 ⟶ 590:
This will set the variable {{code|min}} to {{code|1}} because the condition {{code|(1 < 2)}} is {{code|true}}.
===
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:
Line 580 ⟶ 675:
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">
$result = if $a -eq $b {"was true" } else {"was false"}
</syntaxhighlight>
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>
<syntaxhighlight lang="powershell">
$result = $a -eq $b ? "was true" : "was false"
</syntaxhighlight>
===Python===
Line 588 ⟶ 695:
</syntaxhighlight>
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.
Line 595 ⟶ 702:
The traditional if-else construct in [[R (programming language)|R]] (which is an implementation of [[S (programming language)|S]]) is:
<syntaxhighlight lang="
if (a < b) {
x <- "true"
Line 605 ⟶ 712:
If there is only one statement in each block, braces can be omitted, like in [[C (programming language)|C]]:
<syntaxhighlight lang="
if (a < b)
x <- "true"
Line 614 ⟶ 721:
The code above can be written in the following non-standard condensed way:
<syntaxhighlight lang="
x <- if (a < b) "true" else "false"
</syntaxhighlight>
Line 620 ⟶ 727:
There exists also the function {{code|ifelse}} that allows rewriting the expression above as:
<syntaxhighlight lang="
x <- ifelse(a < b, "true", "false")
</syntaxhighlight>
Line 759 ⟶ 866:
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="
-- General syntax takes case-result pairs, comparing against an expression, followed by a fall-back result:
DECODE(expression, case1, result1,
Line 818 ⟶ 925:
<syntaxhighlight lang="c">
Locals.UUTIndex = ( RunState.Root.Parameters.TestSocket.Index == 3 ? 3 : 0 )
</syntaxhighlight>
===V (Vlang)===
[[V (programming language)|V]] uses ''if expressions'' instead of a ternary conditional operator:<ref>{{Cite web |title=V language documentation |url=https://github.com/vlang/v/blob/master/doc/docs.md#if-expressions |access-date=2025-04-01|website=github}}</ref>
<syntaxhighlight lang="c">
num := 777
var := if num % 2 == 0 { "even" } else { "odd" }
println(var)
</syntaxhighlight>
Line 862 ⟶ 977:
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==
Line 944 ⟶ 1,065:
* [[CoffeeScript]]
* [[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>)
* [[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==
* [[Conditioned disjunction]], equivalent ternary logical connective.
* [[Elvis operator]], {{code|?:}}, or sometimes {{code|?.}}, as a shorthand [[binary operator]]
* [[IIf]], inline if function
* [[McCarthy Formalism]]
* [[Multiplexer]]
* [[Null coalescing operator]], {{code|??}} operator
* [[
==References==
|