Ternary conditional operator: Difference between revisions
Line 25: | Line 25: | ||
if (day == WEEKEND) |
if (day == WEEKEND) |
||
⚫ | |||
⚫ | |||
opening_time = 9; |
opening_time = 9; |
||
⚫ | |||
⚫ | |||
</source> |
</source> |
||
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 ternary operator without an error report upon parsing. This contrasts with if..else ''statements'', where the else clause can be omitted. |
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 ternary operator without an error report upon parsing. This contrasts with if..else ''statements'', where the else clause can be omitted. |
Revision as of 13:16, 29 November 2011
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 or inline if (iif).
It originally comes from CPL, in which equivalent syntax for e1 ? e2 : e3
was e1 → e2, e3
.[1][2]
Conditional assignment
?:
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
This ternary 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 12 o'clock in normal days to 9 o'clock on weekends, we may use
int opening_time = (day == WEEKEND) ? 9 : 12;
instead of the more verbose
int opening_time;
if (day == WEEKEND)
opening_time = 9;
else
opening_time = 12;
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 ternary operator without an error report upon parsing. This contrasts with if..else statements, where the else clause can be omitted.
ALGOL 68
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
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++
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() ? cout : fout;
}
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 ternary 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 a=0, b=0;
const bool cond = ...;
(cond ? a : b) = 1;
std::cout << "a=" << a << ','
<< "b=" << b << '\n';
}
In this example, if the boolean variable cond yields the value true in line 5, the value 1 is assigned to the variable a, otherwise, it is assigned to b.
C#
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;
}
ColdFusion Markup Language
A ColdFusion Markup Language (CFML) example, for the Railo compiler:
<cfscript>
arg = "T";
vehicle = ( ( arg == 'B' ) ? 'bus' :
( arg == 'A' ) ? 'airplane' :
( arg == 'T' ) ? 'train' :
( arg == 'C' ) ? 'car' :
( arg == 'H' ) ? 'horse' :
'feet' );
</cfscript>
<cfoutput>#vehicle#</cfoutput>
Java
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);
JavaScript
The ternary 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,[3] but has been clarified in the December 2009 ECMA-262 specification.[4])
var fooNotNull = (foo != null) ? true : false;
MySQL
This syntax is not SQL standard; it is MySQL specific.
IF(cond,a,b);
Oracle SQL
While Oracle doesn't provide an explicit ternary operator, it does have a variadic functional counterpart which operates similarly to a switch statement and can be used to emulate the ternary 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 ternary operator by just selecting one case:
DECODE(expression, condition, true, false)
The decode
function is, today, depreciated 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
Example of using this operator on Perl:
$secondVar = ($firstVar == 0) ? 0 : @array[0];
PHP
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 equivalent of the above example would yield the value horse instead of train as one would expect. 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 screen.
There is a short-form of the ternary operator:
$c = $a ?: $b; // equivalent to $c = $a ? $a : $b;
Python
Python uses a different syntax for this operator:
value_when_true if condition else value_when_false
This feature is not available for Python versions before 2.5, however. The Python programming FAQ mentions several possible workarounds for these versions.
Ruby
Example of using this operator in Ruby:
1 == 2 ? "true value" : "false value"
Returns "false value".
Visual Basic
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:
Dim opening_time As Integer = IIf((day = WEEKEND), 12, 9)
'general syntax is IIf(condition, value_if_true, value_if_false)
In the above example, IIf
is a function, and not an actual 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 ternary 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 ternary operator, person.Name
is not evaluated unless person is not null
.
Lua
In Lua, the effect of the ternary conditional operator is achieved by the use of two binary operators:
cond and a or b
Result type
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
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.
See also
- Null coalescing operator, ?? operator
References
- ^ 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)" (PDF). BCPL Reference Manual.
- ^ Eich, Brendan (1996-11-18). "Conditional Operator (section 4.14)". JavaScript Language Specification. Retrieved 2010-08-29.
{{cite web}}
: Unknown parameter|coauthors=
ignored (|author=
suggested) (help) - ^ "Conditional Operator (section 11.12, page 93)" (PDF). ECMAScript Language Specification. 2009-12. Retrieved 2010-08-29.
{{cite web}}
: Check date values in:|date=
(help)