I went looking through Raphael.js
's source code to find out how he converted RGB values to HSB. I found out the function he did it in and I was in the process of converting it to Python when I bumped into this nice triple-nested ternary operator:
H = (C == 0 ? null :
V == r ? (g - b) / C :
V == g ? (b - r) / C + 2 :
(r - g) / C + 4
);
It threw me for a loop because Python doesn't have the same kind of ternary operator that Javascript does. I spent a while looking over it and eventually hashed this somewhat saner code (using only if/else) out of it:
if (C == 0) {
H = null;
} else {
if(V == r) {
H = (g - b) / C;
} else {
if(V == g) {
H = (b - r) / C + 2;
} else {
H = (r - g) / C + 4;
}
}
}
Was my interpretation correct? I'm only asking this because if it isn't correct, I'm faced with a lot of debugging. So. Did I "get it"?
I think you can have this to avoid the deep nesting:
var H
if(C == 0){
H = null;
}
else if(V == r){
H = (g - b) / C;
}
else if (V == g){
H = (b - r) / C + 2;
}
else {
H = (r - g) / C + 4;
}
To my personal taste, a carefully aligned nested ternary beats the if-esle mess:
const H =
C == 0 ? null :
V == r ? (g - b) / C :
V == g ? (b - r) / C + 2 :
(r - g) / C + 4 ;
H = C == 0
? null
: V == r
? (g - b) / C
: V == g
? (b - r) / C + 2
: (r - g) / C + 4
I've seen Dan Abramov using this indentation placement pattern. While I don't like how the conditional operator ?
no longer visually follows the condition, I prefer this to something like @lolmaus's example in that the indentation will always be consistent regardless the size of the conditional.
You actually start to look at it as ?
true :
false which is visually intuitive here. And this way, I find the ternary is much easier to spot and differentiate from the surrounding code.
The same logic can be written in a simpler way:
var H
if (C == 0)
H = null;
else if (V == r)
H = (g - b) / C;
else if (V == g)
H = (b - r) / C + 2;
else
H = (r - g) / C + 4;
It's possible to omit the curly braces because there's a single statement in each condition. And given that the conditions are mutually exclusive, using else if
is much clearer than nesting if
s.
Yes, it's right (apart from capitalisation differences). Yet, it may be cleaner written without any parentheses, readable as elseif:
if (C == 0)
h = null;
else if (V == r)
h = (g - b) / C;
else if (V == g)
h = (b - r) / C + 2;
else
h = (r - g) / C + 4;
If your JavaScript codebase contains nested ternary statements like the one in question, consider converting the formatting to daisy chained ternary statements instead.
H = (C == 0) // Is C zero?
? null
: (V == r) // Is V equal to r?
? (g - b) / C
: (V == g) // Is V equal to g?
? (b - r) / C + 2
: (r - g) / C + 4; // Fallback (default) value
They simply read top to bottom in a straight line, returning a value
as soon as they hit a truthy condition or the fallback.
–Nested Ternaries are Great, Eric Elliot