DEV Community

Cover image for โœ”||๐Ÿคข Commit or Vomit  | nested ternary operator

โœ”||๐Ÿคข Commit or Vomit | nested ternary operator

The ternary operator

It's a delight to use them but should we use them as much as possible? what do you think about the next example? โœ”||๐Ÿคข

H = (C == 0 ? null :
    V == r ? (g - b) / C :
    V == g ? (b - r) / C + 2 :
             (r - g) / C + 4
    );
Enter fullscreen mode Exit fullscreen mode

nested ternary operators โœ”||๐Ÿคข?

โค: Commit (I'd commit something like this)
๐Ÿท: Vomit (we all know unicorns don't vomit)
๐Ÿฆ„: Like your post please continue this series!

Let's vote! ๐Ÿ˜Š

Photo by Science in HD on Unsplash

Top comments (36)

Collapse
 
jackmellis profile image
Jack

There's a reason there are eslint rules banning nested turnaries ๐Ÿคฎ

Collapse
 
lexlohr profile image
Alex Lohr

I find the readability of the ternary operator depends very much on the formatting. The default settings of prettier pretty much nails it - here's a rendition of your code:

H = C == 0
  ? null
  : V == r
  ? (g - b) / C
  : V == g
  ? (b - r) / C + 2
  : (r - g) / C + 4;
Enter fullscreen mode Exit fullscreen mode

What I don't like is mix-and-match. If you are using comparisons with multiple branches, be sure to use switch or if-else, but don't mix between them, as it reduces readability.

Collapse
 
idanarye profile image
Idan Arye

How is this formatting better than the original? The original is organized like a table, where the first column is the variable that accepts the result (only has a value in the first row, but that's fine), the second is the condition (which is empty for the last row, meaning "no condition - if all previous conditions were false) and the last is value.

This formatting, on the other hand, provides no hints regarding the role of each expression - they all start in the same column. Initially it may look like lines starting with ? are conditions and lines starting with : are result expressions, but this is not true for the last line. And yes, this is a property of the language's syntax, not the formatting, but OP's formatting was able to solve this with the tabular design and when the prettier flattened everything that hint was lost.

In this regard, I prefer Python's conditional operator. Manually formatted it looks better than OP's formatting of C conditionals, because I don't need to put lots of space before the last, condition-less result expression:

H = None if C == 0 else \
    (g - b) / C if V == r else \
    (b - r) / C + 2 if V == g else \
    (r - g) / C + 4
Enter fullscreen mode Exit fullscreen mode

But even if I prettify it with Black I get this:

H = (
    None
    if C == 0
    else (g - b) / C
    if V == r
    else (b - r) / C + 2
    if V == g
    else (r - g) / C + 4
)
Enter fullscreen mode Exit fullscreen mode

And yes - just like your prettified C code it is flat, but at least here, thanks to the language's syntax, the structure is clear - all lines starting with if are conditions and all lines starting with else are result expressions - so it's still readable.

Collapse
 
lexlohr profile image
Alex Lohr

It's JS, not C, and the secret to reading it is in the rythm:

Q1
? Y1
: N1/Q2
? Y2
: N2;
Enter fullscreen mode Exit fullscreen mode

Once you're used to the pattern, it is more legible than the other version.

That being said, I really like the verbose ternary of Python and Rust. Unfortunately they'll never be supported by ECMAscript.

Thread Thread
 
idanarye profile image
Idan Arye

Rust is a different story. It's not a ternary conditional operator there - it's a full blown if expression and any prettifier would format it with proper indentations:

let H = if C == 0 {
    None
} else if V == r {
    Some((g - b) / C)
} else if V == g {
    Some((b - r) / C + 2)
} else {
    Some((r - g) / C + 4)
};
Enter fullscreen mode Exit fullscreen mode
Collapse
 
khorne07 profile image
Khorne07

The only reason people keep complaining about the readability of nested ternary operators is because they don't use it enough. This example looks quite readable to me and I'll always prefer this way over the verbosity of if - else blocks.

Collapse
 
jmdejager profile image
๐Ÿค๐Ÿฅ‡ Jasper de Jager

I can understand that but you don't write code only for yourself so it is interesting to see what others think. I'd rather not use it if it is not common enough.

Collapse
 
khorne07 profile image
Khorne07

Fair though, but maybe if more people were using it, it wouldn't have so many people hating it. In my case when I started learning Js I didn't like it too much, I found it unnecessary since you can go with if - else blocks like in other languajes (I came to learn js from C, C++ and C#). But after facing real world codes using this sintax I were forced to learn it and understand it well so now is very natural for me to see and work with nested ternaries, and ended up loving them.

Thread Thread
 
khorne07 profile image
Khorne07

So taking my self by guide, when someone says nested ternaries are hard to understand or using them decrese code readability, my conclusion is that they haven't used ternaries enough, or still don't have enough experience in js, so facing them would be a good way to improve their logic skills and learn a new concise way of write conditional statements blocks

Thread Thread
 
jmdejager profile image
๐Ÿค๐Ÿฅ‡ Jasper de Jager

Yes and that's one thing I'm trying to find out with these series โ˜บ๏ธ is it something That's not ok or just something for the more experienced developer. Your comments help a lot!! ๐Ÿ˜Ž

Thread Thread
 
tominflux profile image
Tom

It's really not about one's ability to read ternaries. It's about code writing/analysing efficiency. Even a senior dev will be disadvantaged by encountering a complex nested ternary because the context is not explicit and they have to spend some time analysing it. These kind of ternaries always come with a large cognitive load. Always value being concise over ~quick~ readability, and your codebase will become a nightmare to maintain.

Thread Thread
 
jmdejager profile image
๐Ÿค๐Ÿฅ‡ Jasper de Jager

I totally agree!

Thread Thread
 
khorne07 profile image
Khorne07

Well that actually depends on the situation. Ternaries are not to include on every conditional situation, that is a horror ๐Ÿ˜‚. I'm just saying that I rather use a nested ternary over an if-else block. If there is no need to use an if-else block, then there shouldn't been any nested ternary there either.

Collapse
 
tominflux profile image
Tom

If you stumble across something like this in a large codebase when you need to get something implemented/fixed quickly, it's a bloody nightmare.

Takes ages to grasp the context of what this kind of code is trying to do. It's always worth putting each sub-condition in a named boolean constant.
e.g. const doesProfileExist = ...

And then using a fail-fast if statement straight after.
e.g. if (!doesProfileExist) return x

Collapse
 
cabbage profile image
cab

So yeah, that code right there is garbage. But IMO that's not because of the nested ternary but because of the naming of your operands. And as @lexlohr said the formatting should also in way that it aids the readability. However, I'm uncertain about the prettier formatting is the way I'd do it. Maybe this is a bit more clear?

H = C == 0
  ? null
  : V == r
    ? (g - b) / C
    : V == g
      ? (b - r) / C + 2
      : (r - g) / C + 4;
Enter fullscreen mode Exit fullscreen mode

(aside: my operand naming: condition ? left : right)
Becaus the prettier formatting only works that way if the right operand is always the condition for the next ternary. If one would mix this 'rule' it would be more confusing if the nested ternaries would not be indented.

Nevertheless: Only do it when it serves the readability and use proper names for your operands. Then I'm ok with it. Otherwise ๐Ÿคฎ

PS: idgaf if you one calls it conditional or ternary. I cannot remember hearing 'conditional operator' in 15 years in several languages.

Collapse
 
jonrandy profile image
Jon Randy ๐ŸŽ–๏ธ

You know it's called the conditional operator, right? It just happens to be a ternary operator (one that takes 3 operands)

Collapse
 
andreidascalu profile image
Andrei Dascalu

Hmm, in all languages I know this is the only conditional operator though the common way to name it depends. In Java it's generally the conditional operator while in PHP it's commonly the ternary operator.
But I am really curious, do you know a language where there is another kind of conditional operator that is not a ternary?

Collapse
 
jonrandy profile image
Jon Randy ๐ŸŽ–๏ธ

Yes, I'm a hoot at parties! ๐Ÿ˜‹

Collapse
 
jmdejager profile image
๐Ÿค๐Ÿฅ‡ Jasper de Jager

Don't forget to vote on your way out ๐Ÿ˜‰

Collapse
 
jmdejager profile image
๐Ÿค๐Ÿฅ‡ Jasper de Jager

I just love it when I make mistakes โ˜บ๏ธ means I've learned something ๐Ÿ˜Ž

Collapse
 
jmdejager profile image
๐Ÿค๐Ÿฅ‡ Jasper de Jager

Hah good one, thanks

Collapse
 
renanlazarotto profile image
Renan "Firehawk" Lazarotto

Not only I would vomit on something like this, I'd be sure to vomit on the one that did it in the first place.

Collapse
 
darkwiiplayer profile image
๐’ŽWii ๐Ÿณ๏ธโ€โšง๏ธ

Definitely commit. It looks a bit weird when you're not used to seeing it, but otherwise it looks ok :D

Collapse
 
jankapunkt profile image
Jan Kรผster

Please don't do it. It's not only about readable code. What If logic requirements change and you need to o rewrite this... I don't want to be assigned to that kind of job

Collapse
 
jmdejager profile image
๐Ÿค๐Ÿฅ‡ Jasper de Jager

Good point

Collapse
 
natalia_asteria profile image
Natalia Asteria • Edited

Using nested conditional operator is a federal crime. We should call the FBI.

Collapse
 
blindfish3 profile image
Ben Calder

Your polling strategy is flawed: that is so bad I don't want it appearing in my reading list ๐Ÿคฎ

Collapse
 
jmdejager profile image
๐Ÿค๐Ÿฅ‡ Jasper de Jager

You make a good point, but unicorns don't vomit, any ideas? ๐Ÿ˜‰