• Nested Ternaries are Great
  • By Eric Elliott
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: yoyoyohamapi
  • Proofreader: StarrieC goldEli

(See Flickr for this image of the smoke squaring in Photoshop.)

This is the fourteenth installment in the “Writing Software” series on learning functional programming and compositional software techniques from scratch in JavaScript ES6+

On a | < < < return to the first article

Past experience would have you believe that nested ternary expressions are unreadable and should be avoided as much as possible.

Experience is sometimes stupid.

The truth is that ternary expressions are usually simpler than if statements. People don’t believe it for two reasons:

  1. They are more familiar with the if statement. Familiarity biases can lead us to believe things that are not true, even when we provide evidence for the truth.
  2. People try to use ternary expressions like if statements. Such code does not work because a ternary expression is an expression, not a statement.

Before we dive into the details, let’s define a ternary expression:

A ternary expression is a conditional expression that evaluates. It consists of a condition judgment, a truthy value (the value returned when the condition is true) and a falsy clause (the value returned when the condition is false).

They look like this:

(conditional)
  ? truthyClause
  : falsyClause
Copy the code

Expression vs statement

Some programming languages (including Smalltalk, Haskell, and most functional programming languages) do not have if statements. Instead, the if expression.

An if expression is a conditional expression that evaluates. It consists of a condition judgment, a truthy value (the value returned when the condition is true) and a falsy clause (the value returned when the condition is false).

Does this definition look familiar? Most functional programming languages use ternary expressions to represent the if keyword. Why is that?

An expression is a block of code that evaluates a single value.

A statement is a piece of code that does not necessarily evaluate. In JavaScript, an if statement is not evaluated. In order for an if statement in JavaScript to be useful, it must either cause a side-effect or return a value in the code block that the if statement wraps around.

In functional programming, we try to avoid variability and other side effects. Because of the inherent variability and side effects of if in JavaScript, some proponents of functional programming, myself included, use ternary expressions instead.

Ternary expressions have a different mind-set than if statements, but if you experiment with them for a few weeks, you’ll naturally migrate to ternary expressions. Not only does it reduce the amount of code, but you’ll see some of the benefits later in this article.

Familiarity brings prejudice

The most common complaint I hear about ternary expressions is that they are “hard to read.” Let’s squash the rumors with some code examples:

const withIf = ({
  conditionA, conditionB
}) => {
  if (conditionA) {
    if (conditionB) {
      return valueA;
    }
    return valueB;
  }
  return valueC;
};
Copy the code

Notice that in this version, true and false values are separated by nested conditions and visible parentheses, which makes true and false values seem disconnected. It’s a simple logic, but one that takes effort to understand.

Let’s see how the same logic works with ternary expressions:

constwithTernary = ({ conditionA, conditionB }) => ( (! conditionA) ? valueC : (conditionB) ? valueA : valueB );Copy the code

Here are some points worth sharing and discussing:

Daisy chain vs. nesting

Daisy Chaining refers to the joining of multiple devices in order or in a loop.

First, we’ve smoothed out nesting. “Nested” ternary expressions are a bit of a misnomer, because ternary expressions are easy to write in a straight line and you don’t need to use different indents to nest them at all. They tend to read from top to bottom in straight line order, returning as soon as a certain truth or false value is met.

If you write ternary expressions correctly, there is no need to resolve any nesting. Walking in a straight line, it’s hard to get lost.

We should call this a “chained ternary” rather than a “nested ternary”.

One other thing I’d like to point out is that I’ve changed the order slightly to simplify straight linking: If you reach the end of a ternary expression and find that you need to write two colon clauses (:) :

// The translator added this situation
const withTernary = ({
  conditionA, conditionB
}) => (
  conditionA
    ? conditionB
    ? valueA
    : valueB
    : valueC
)
Copy the code

Mention the last clause in the header, and reverse the first conditional logic to simplify parsing the ternary expression. Now, there’s no more confusion!

Note that we can use the same trick to simplify the if statement:

const withIf = ({
  conditionA, conditionB
}) => {
  if(! conditionA)return valueC;
  if (conditionB) {
    return valueA;
  }
  return valueB;
};
Copy the code

That’s much better, but conditionB’s broken correlation clause is still visible, which can cause confusion. I’ve seen logic bugs caused by similar problems while maintaining the code. Even with the logic flattened, this version of the code is a little messier than the ternary version.

Grammar chaos

The if version of the code contains a lot of noise: the if keyword vs? , use return to force statements to return a value, extra semicolons, extra parentheses, and so on. Unlike the examples in this article, most if statements also change the external state, which not only increases the code, but also increases its complexity.

The negative impact of this extra code is one of the main reasons I don’t like using if. I’ve talked about this before, but before every developer knows, I’d like to repeat:

Working memory

On average, the human brain has only a small shared resource for the discrete quanta stored in working memory, and each variable subtly consumes these quanta. As you add more variables, you lose the ability to accurately remember what those variables mean. Typically, the working memory model involves 4-7 discrete words. Beyond that, the error rate skyrockets.

In contrast to ternary expressions, we have to incorporate variability and side effects into if statements, which often results in adding variables that are not needed.

Signal to noise ratio

Concise code will also improve the signal-to-noise ratio of your code. It’s like listening to a radio – if the radio isn’t tuned to a certain channel correctly, you’ll hear a lot of noise, so it’s hard to hear music. When you tune in to the right channel, the noise goes away and you hear a strong musical signal.

The code is similar. The more concise the expression, the easier it is to understand. Some of the code gives us useful information, some leaves us in the dark. If you can reduce the amount of code without losing the message, you’ll make the code easier to parse and easier for other developers to understand.

The surface area for hiding bugs

Look at the front and back of the function. It’s as if the function has gone on a diet and lost tons of weight. This is important because extra code means more surface area for hiding bugs, which means more bugs.

Less code = less surface area for hiding bugs = fewer bugs.

Mutable state of side effects and sharing

Many if statements do more than evaluate. They also cause side effects, or change the state, and if you want to know the full impact of the if statement, you need to know the effect of the side effects in the if statement, the history of all the changes to the shared state, and so on.

Limiting yourself to returning a value forces you to follow the principle that severing dependencies will make your program easier to understand, debug, refactor, and maintain.

This is indeed my favorite benefit of ternary expressions:

Using ternary expressions will make you a better developer.

conclusion

Since all ternary expressions tend to be allocated from the top down using a straight line, calling them “nested ternary expressions” is a bit of a misnomer. Instead, we call them “chained ternary expressions.”

Chained ternary expressions have several advantages over if statements:

  • It is always easy to read and write top-down through a straight line. As long as you can walk in a straight line, you can read chained ternary expressions.
  • Ternary expressions reduce syntax clutter. Less code = less surface area for hiding bugs = fewer bugs.
  • Ternary expressions do not require temporary variables, which reduces the load on working memory.
  • Ternary expressions have better signal-to-noise ratios.
  • If statements encourage side effects and variability. Ternary expressions encourage pure code.
  • Pure code decouples our expressions from our functions, and thus trains us to be better developers.

Learn more at EricElliottJS.com

Video lessons and functional programming are ready for members of EricElliottJS.com. If you’re not already one of them, sign up now.


Eric Elliott is the author of “Write JavaScript Apps” (O ‘Reilly) and “Learn JavaScript with Eric Elliott.” He has contributed to many companies and organizations, such as Adobe Systems, Zumba Fitness, The Wall Street Journal, ESPN and BBC, and is a top artist for many organizations, Including but not limited to Usher, Frank Ocean and Metallica.

He spent most of his time in the San Francisco Bay Area with the most beautiful women in the world


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.