?:
In computer programming, ?: is a ternary operator that is part of the syntax for a basic conditional expression in several programming languages. It is commonly referred to as the conditional operator, inline if (iif), or ternary if.
It originally comes from CPL, in which equivalent syntax for e1 ? e2 : e3 was e1 → e2, e3.[1][2]
Contents
|
Conditional assignment [edit]
?: 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, and Haskell, 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 opening hours from 9 o'clock during weekdays to 12 o'clock on weekends, we may use
int opening_time = (day == WEEKEND) ? 12 : 9;
instead of the more verbose
int opening_time; if (day == WEEKEND) 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
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 )
- Chained if choice clause:
if condition1 then statements elif condition2 then statements [ else statements ] fi "brief" form: ( condition1 | statements |: condition2 | statements | statements )
C [edit]
A traditional if-else construct in C, Java and JavaScript is written:[3]
if (a > b) { result = x; } else { result = y; }
This can be rewritten as the following statement:
result = a > b ? x : y;
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 if x is an expression, it is evaluated only once. The difference is significant if evaluating the expression has side effects.
C# and Perl provide similar functionality with their null coalescing operator.
a = x ?? y;
(Unlike the above usage of "x ?: y", ?? will only test if x is non-null, as opposed to non-false.)
C++ [edit]
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. 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:
#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!" << std::endl; return 0; }
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 a 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 << std::endl; return 0; }
In this example, if the boolean expression argc > 1 yields the value true in line 5, the value 1 is assigned to the variable a, otherwise, it is assigned to b.
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. 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; }
CoffeeScript [edit]
Example of using this operator in CoffeeScript:
if 1 is 2 then "true value" else "false value"
Returns "false value".
ColdFusion Markup Language [edit]
A ColdFusion Markup Language (CFML) example, for the Railo compiler:
<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' /** EXAMPLE 2 **/ price = 1000; hasPrice = ( price > 0 ) ? true : false; // returns true </cfscript>
Common Lisp [edit]
Assignment using a conditional expression in Common Lisp:
(setf result (if (> a b) x y))
Imperative form:
(if (> a b) (setf result x) (setf result y))
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)
Java [edit]
In Java this expression evaluates to:
if foo is selected assign selected foo to bar else assign selected baz to bar.
Object bar = foo.isSelected() ? getSelected(foo) : getSelected(baz);
Note that Java 7, in a manner similar to C#, only evaluates the used expression and will not evaluate the unused expression.[4]
JavaScript [edit]
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 l-value. (This situation apparently was improperly specified in the original JavaScript specification,[5] but has been clarified in the December 2009 ECMA-262 specification.[6])
var fooNotNull = (foo !== null) ? true : false;
Similar to PHP's short-hand operator, JavaScript programmers have long since used the OR operator, which functionally produces the same results. Although, this type of "short-hand" is technically considered a null coalescing operator. See below:
var aVar = bVar || cVar; // equivalent to `var aVar = bVar ? bVar : cVar`
The above is often used when optimizing code.
Lua [edit]
Lua doesn't have a traditional conditional operator. However, the short-circuit 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 (false or nil); in this case, the expression will always result in b. This can result in some surprising behaviour if ignored.
MySQL [edit]
This syntax is not SQL standard; it is MySQL specific.
IF(cond,a,b);
Oracle SQL [edit]
While Oracle doesn't provide an explicit conditional operator, it does have a 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).
-- 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 Oracle's full switch statement, case. This can be used in both Oracle SQL queries as well as PL/SQL blocks, whereas decode can only be used in the former.
Perl [edit]
A traditional if-else construct in Perl or PHP is written:
if ($a > $b) { $result = $x; } else { $result = $y; }
Rewritten to use the conditional operator:
$result = ($a > $b) ? $x : $y;
Another example of using this operator on Perl:
$secondVar = ($firstVar == 0) ? 0 : $array[0];
Perl 6 [edit]
Uses double "?" symbols and double "!" instead of ":":[7]
$result = ($a > $b) ?? $x !! $y;
PHP [edit]
A simple PHP implementation is this:
<?php $valueOne = (5 > 1) ? true : false; ?>
<?php $arg = "T"; $vehicle = ( ( $arg == 'B' ) ? 'bus' : ( $arg == 'A' ) ? 'airplane' : ( $arg == 'T' ) ? 'train' : ( $arg == 'C' ) ? 'car' : ( $arg == 'H' ) ? 'horse' : 'feet' ); echo $vehicle; ?>
Due to an unfortunate error in the language grammar, the implementation of ?: in PHP uses the incorrect associativity when compared to other languages, and given a value of T for arg, the PHP code in the above example would yield the value horse instead of train as one might expect.[8] 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[9] and will probably not change.[10] 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 correct result of train being printed to the output.
PHP 5.3 [edit]
Since PHP 5.3 there is a short-hand of the conditional operator.[11] Although, this short-hand is technically considered a null coalescing operator. The syntax for this short-hand is below:
$c = $a ?: $b; // equivalent to $c = $a ? $a : $b;
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:
result = x if a > b else y
This form invites considering x as the normal value and y as an exceptional case. One can use the syntax
(lambda:y, lambda:x)[a > b]()
as a workaround for code that also needs to run under Python versions before 2.5. Note that operands are lazily evaluated, it is possible to remove the lambdas and function calls but the operands will be eagerly evaluated which isn't consistent with the conditional operator of most other languages, e.g. by indexing a tuple,
result = (y, x)[a > b]
or using an explicitly constructed dictionary:
result = {True: x, False: y}[a > b]
A less reliable but simpler to read alternative is to abuse the and and or operators and write
result = (a > b) and x or y
but this code would break if x could be a "falsy" value (None, False, 0, an empty sequence or collection, …) as the expression would return y (whether it was truthy or falsy) instead of the (falsy) x. A possible workaround is to make x and y lists or tuples, so they are never falsy, and then grab the first element of the resulting sequence as in the following
result = ((a > b) and [x] or [y])[0]
or
result = ((a > b) and (x,) or (y,))[0]
NB when wrapping Python's conditional construct into a utility function, the unalterably eager nature of the more intuitive language construct for side-effect functions
func = lambda b,a1,a2 : (a1,a2)[not b] def true(): print "true" return "truly" def false(): print "false" return "falsely" func(True, true(), false()) true false 'truly' func(False, true(), false()) true false 'falsely'
similar results from
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]()
as the correct call would be
func(True, true, false)() true 'truly' func(False, true, false)() false 'falsely'
however the python 2.5 construct is safer; calling the construct directly works more intuitively
true() if True else false() true 'truly' true() if False else false() false 'falsely'
clearly the reason being that in the case of
func(True, true(), false())
the functions are called when sent as parameters rather than when returned from func()
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:[12]
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
PL/SQL [edit]
A specific conditional operator for PL/SQL is not available, but a special case of the CASE expression works exactly as a conditional operator:
SELECT (CASE WHEN a > b THEN x ELSE y END) AS "Conditional_Example" FROM DUAL;
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 )
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 = WEEKEND), 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.
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 weekends, 9 for other days } Result := IfThen((Weekday = 1) or (Weekday = 7), 12, 9); end;
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]
Some corporate programming guidelines list the use of the conditional operator as bad practice because it can harm readability and long-term maintainability.[citation needed] 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.)
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:
- Go programming language[13]
- Pascal Although Object Pascal / Delphi do have a function
IfThento do the same
See also [edit]
- IIf, inline if function
- Null coalescing operator, ?? operator
References [edit]
- ^ Strachey, Christopher (2000). "Fundamental Concepts in Programming Languages". Higher-Order and Symbolic Computation 13: 11–49. doi:10.1023/A:1010000313106.
- ^ "BCPL Ternary operator (page 15)". BCPL Reference Manual.
- ^ Learning GNU C: The Conditional Operator
- ^ Java 7 Specification: 15.25 Conditional Operator ? :
- ^ Eich, Brendan; C. Rand McKinney (1996-11-18). "Conditional Operator (section 4.14)". JavaScript Language Specification. Retrieved 2010-08-29.
- ^ "Conditional Operator (section 11.12, page 93)" (PDF). ECMAScript Language Specification. 2009-12. Archived from the original on 16 August 2010. Retrieved 2010-08-29.
- ^ "Perl6 Operators". Larry Wall. Retrieved 2010-05-18.
- ^ Eevee (2012-04-09). "PHP: a fractal of bad design". Retrieved 2013-04-26.
- ^ "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"
- ^ "PHP 5.3.0 Release Announcement". PHP website. Retrieved 2013-04-26. "Syntax additions: NOWDOC, ternary short cut "?:" and jump label (limited goto), __callStatic()"
- ^ Programming Ruby: Conditional Execution
- ^ "Does Go have the ?: operator?". The Go Programming Language FAQ. Retrieved 2012-08-05.
External links [edit]
- Description of Conditional Operator in C#
- Description of If operator in Visual Basic
- Description of Conditional Expression in Python (PEP 308)
- Alternative workaround for conditional operator expression in Python
- Description in the Java Language Specification
- Description in the PHP Language Documentation
- Visual Basic 9.0 Language Specification