2

I have been introduced to the concept of ternary operators, and it's pretty straightforward to understand the notation:

desired_variable = true ? false ? "value1" : "value2";

I could not understand, however, the rational behind adding a second variable, even if I understand the answer. To use a classic example:

var eatsPlants = false;
var eatsAnimals = false;
var category;

category = eatsPlants ? eatsAnimals ? "omnivore" : "herbivore" : eatsAnimals ? "carnivore" : undefined;
console.log(category)

Here, one observation: If I change the order of the variables to the statement below, the function does not work:

category = eatsAnimals ? eatsPlants? "carnivore" : undefined : eatsPlants ? "herbivore" : "omnivore";
console.log(category)

My question: why doesn't the function work when the terms are inverted? And how do I choose the order of the terms when I have two or more variables (and therefore four or more results)?

pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
cgobbet
  • 309
  • 4
  • 12
  • there is only one questionmark and colon in a single ternary, like `variable = comparison ? value1 : value2;` – Nina Scholz Mar 09 '19 at 19:18
  • 1
    In general, if your ternary operator is not *super* simple, you should probably avoid writing the logic as a ternary operator and just do `if/else` instead. There is no advantage to having all in one line if it takes you any longer to read and understand what it happening. – VLAZ Mar 09 '19 at 19:20
  • I agree abour the if/else would be clearer. The issue is that I am trying to get the logical thinking more than the final outcome. – cgobbet Mar 10 '19 at 09:53

5 Answers5

4

Ternary expressions have 3 expressions inside of them. However, because ternary expressions are themselves expressions you can put ternary expressions inside other ternary expressions. The ternary expressions in your example above look so confusing because they are multiple nested ternary expressions. This confusion can be better cleared up with formatting and use of parentheses:

var eatsPlants = false;
var eatsAnimals = false;
var category = null;

category =
  (eatsPlants ?
    (eatsAnimals ? "omnivore" : "herbivore")
    :
    (eatsAnimals ? "carnivore" : undefined)
  );
console.log(category);
pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
3

You can understand by this example.

x ? ( y ? a : b ) : c
|
|________true   ---> y ? a : b
|
|________false  ---> c
  • first check the value of x if it is true it will run y ? a : b (i have added () just for readability )
  • If it is false it will go to c

You can simply understand it same as if/else, if i change above code to if/else

if(x){
  if(y) {
    return a
  } else {
    return b
} else {
   return c
 }
}
Code Maniac
  • 37,143
  • 5
  • 39
  • 60
2

To get a right result, you could group the ternaries and maintain the same level of decisions.

var eatsPlants = false,
    eatsAnimals = false,
    category = eatsPlants
        ? eatsAnimals
            ? "omnivore"
            : "herbivore"
        : eatsAnimals
            ? "carnivore"
            : undefined;

console.log(category);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

You cannot change the order between then and else parts, as that affects the outcome (if you don't also negate the condition). You can however change the nesting, and write either

category = eatsPlants
  ? eatsAnimals
      ? "omnivore"
      : "herbivore"
  : eatsAnimals
      ? "carnivore"
      : undefined;

or

category = eatsAnimals
  ? eatsPlants
      ? "omnivore"
      : "carnivore"
  : eatsPlants
      ? "herbivore"
      : undefined;
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
1

A ternary operation always takes three operands, like:

inputExpression ? outputExpressionIfTrue : outputExpressionIfFalse

The code in the question is using the output from some ternary operations as the input expression for others, which can be seen more clearly if we format it like in this code snippet. In each case, the outer operation returns the result of whichever inner operation runs (and the comments explain which inner operation runs and what it returns.)

var eatsPlants = false;
var eatsAnimals = false;
var category;

category = eatsPlants
  ? (eatsAnimals ? "omnivore" : "herbivore") // doesn't run because eatsPlants is false
  : (eatsAnimals ? "carnivore" : undefined); //returns undefined because eatsAnimals is false 
console.log(category);

category = eatsAnimals
 ? (eatsPlants ? "carnivore" : undefined) // doesn't run because eatsAnimals is false
 : (eatsPlants ? "herbivore" : "omnivore"); // returns "omnivore" because eatsPlants is false
console.log(category);

Note that to handle information about categories of things with similar properties, it may be helpful to use objects, like:

const carnivore =  {
  eatsPlants: false,
  eatsAnimals: true
};
const herbivore =  {
  eatsPlants: true,
  eatsAnimals: false
};
const omnivore =  {
  eatsPlants: true,
  eatsAnimals: true
};

console.log("carnivore:");
console.log("  eatsPlants: " + carnivore.eatsPlants);
console.log("  eatsAnimals: " + carnivore.eatsAnimals);
console.log("herbivore:");
console.log("  eatsPlants: " + herbivore.eatsPlants);
console.log("  eatsAnimals: " + herbivore.eatsAnimals);
console.log("omnivore:");
console.log("  eatsPlants: " + omnivore.eatsPlants);
console.log("  eatsAnimals: " + omnivore.eatsAnimals);  
Cat
  • 4,141
  • 2
  • 10
  • 18