Here’s a puzzle that’s hard if you don’t know how to read the ?: operator, and relatively easy otherwise: The answer is the same in C, C++, C#, and Java. First things first: the above code is terribly formatted. It reads like a run-on sentence, instead of exposing the underlying structure. I actually wrote the code as a run-on sentence on purpose because, in my opinion, getting the formatting right is basically the same thing as solving the puzzle. Properly formatted code makes the correct interpretation obvious. I almost feel like I’m giving it away, formatting it for you: (Here’s a controversial statement: I consider the above formatted code to qualify as “very readable”.) The trick to reading nested conditional (“ternary”) expressions is to read them as if-then-else expressions. If-then-else expressions, if they existed, would work exactly like if-statements except they would choose between expressions instead of statements. Translating the puzzle into if-then-else expressions should make the answer dead obvious: If that’s still not clear, here’s the same thing as if-statements: Right, the solution is “c”. First the “a” branch is not taken because 5 is not a multiple of 2. Then the “b” branch is not taken since 5 is not a multiple of 3. Then the “c” branch is chosen because 5 is a multiple 5, making the result “c”. This reasoning works for both the if-statements variant, the if-then-else variant, and the conditional operator variant. Trivial: Nesting inside the else: Nesting inside the then: Fizz buzz, nesting inside both: I hope those were helpful, and made you wish we had if-then-else expressions instead of the conditional operator. Read conditional operators as a sequence of if/else cases. That is to say, read "a ? b : c" as "if a then b else c". This is especially helpful when there's nesting, because the leading "if" disambiguates the meaning. Be wary of writing nested conditional operators, even when they make a nice if-elseif-elseif-...-else pattern. You're assuming readers will know how to read conditional operators, which they might not, and so they may consider your code unreadable. (Deciding on what level of knowledge is required of readers, and permitted of writers, is kind of a difficult social problem.) Next level of difficulty: suppress everything you just learned, and figure out how PHP horses everything up by choosing "d" instead of "c". --- --- ---
How to Read Nested Ternary Operators
int i = 5;
string result = i % 2 == 0 ? "a" : i % 3 == 0 ? "b" : i % 5 == 0 ? "c" : i % 7 == 0 ? "d" : "e";
// what is the value of result?
Step 1: Fix Formatting
int i = 5;
string result = i % 2 == 0 ? "a"
: i % 3 == 0 ? "b"
: i % 5 == 0 ? "c"
: i % 7 == 0 ? "d"
: "e";
Step 2: As If
int i = 5;
string result = if i % 2 == 0 then "a"
else if i % 3 == 0 then "b"
else if i % 5 == 0 then "c"
else if i % 7 == 0 then "d"
else "e";
int i = 5;
string result;
if (i % 2 == 0) {
result = "a";
} else if (i % 3 == 0) {
result = "b";
} else if (i % 5 == 0) {
result = "c";
} else if (i % 7 == 0) {
result = "d";
} else {
result = "e";
}
Examples
i % 2 == 0 ? "even" : "odd";
// Translated:
if i % 2 == 0 then "even" else "odd";
i % 2 == 0 ? "even" : i < 0 ? "nodd" : "podd";
// Formatted:
i % 2 == 0 ? "even"
: i < 0 ? "nodd"
: "podd";
// Translated:
if i % 2 == 0 then "even"
else if i < 0 then "nodd"
else "podd";
i % 2 == 0 ? i % 4 == 0 ? "even steven" : "even" : "odd";
// Formatted:
i % 2 == 0 ?
i % 4 == 0 ? "even steven"
: "even"
: "odd";
// Translated:
if i % 2 == 0 then
if i % 4 == 0 then "even steven"
else "even"
else "odd";
i % 2 == 0 ? i % 3 == 0 ? "fizzbuzz" : "fizz" : i % 3 == 0 ? "buzz" : i.ToString();
// Formatted (note: This case is too complicated. You won't get hired if you write it like this.):
i % 2 == 0 ?
i % 3 == 0 ? "fizzbuzz"
: "fizz"
: i % 3 == 0 ? "buzz"
: i.ToString();
// Translated:
if i % 3 == 0 then
if i % 5 == 0 then "fizzbuzz"
else "fizz"
else if i % 5 == 0 then "buzz"
else i.ToString();
Summary
Discuss on Reddit
My Twitter: @CraigGidney
One Response to “How to Read Nested Ternary Operators”
Twisted Oak Studios offers consulting and development on high-tech interactive projects. Check out our portfolio, or Give us a shout if you have anything you think some really rad engineers should help you with.
Archive
Fizz buzz, nesting inside both ‘//Translated’ should be (typo?):
if i % 2 == 0 then
if i % 3 == 0 then “fizzbuzz”
else “fizz”
else if i % 3 == 0 then “buzz”
else i.ToString();