There is a very specific pitfall with ternary operators in statically typed languages which allow type coercions, like Java. Programmers like to refactor code like this to avoid repetition:
if(condition) {
System.out.println(3);
} else {
System.out.println(4.5);
}
This can almost be rewritten as:
System.out.println(condition ? 3 : 4.5);
Unfortunately, the two are not equivalent, as the first version prints 3
when the condition is true, whereas the second version prints 3.0
because the ternary expression needs to have a static type, so it's double
. In general with overloaded methods this can cause arbitrarily different behaviour, though it only rarely makes a difference; I only came across this once when writing an interpreter in Java, where a method like this had a bug because I was too eager to simplify it:
Object getDefaultValue(Type t) {
if(t == Type.DOUBLE) {
return 0.0;
} else {
return 0;
}
}
The refactored version unconditionally returns a boxed value of 0.0
as a Double
, because ... ? 0.0 : 0
coerces to double
before the result is coerced to Object
.
It's genuinely rare for this refactoring to cause a significant problem in code, so this isn't really an argument against having the ternary operator in your language. But generally no programmer ever wants two type conversions in a row (here, 0
gets coerced to double
then Object
) without making both conversions explicit, so it's something to be careful of. (Perhaps there should be a warning for serial implicit type conversions.)
?:
(ternary conditional) operator? $\endgroup$