Multiple lines in a ternary operator's clauses?

Continuing the discussion from Ternary if() elseif() else:

How can you have multiple var declarations for example in the second expression (I mean the “else” clause)? Can you just separate each declaration with a semicolon?

I’m pretty sure the answer to your question is “no”. The semi-colon is used to indicate the end of the ternary operation, so having more than one action within the true or false won’t work. At least, not from my experience.

Ternary operations are for simple, single actions. If you have to do more than one thing in a true or false, use a standard if/else process, because the following code, nested or not, will not work.

a === 'true' ? b = 1; c=2; : b = 3; c = 4; ;

HTH,

:slight_smile:

Ternary operations are intended to be simple, so you’re asking to do something which is outside the realm of what it’s intended to do.

//this
$var = $action == 'edit' ? 'Edit' : ($action == 'delete' ? 'Delete' : 'New');

// is the same as this
if ($action == 'edit') {
   $var = 'Edit';
} else if ($action == 'delete') {
   $var = 'Delete';
} else {
  $var = 'New';
}

Notice how everything ends up going into $var. It’s a simple operation, and this pattern is the shorthand version of that operation (programmers are inherently lazy, which is why patterns like this exist). If you want to assign a value to a secondary variable, then this pattern is not the one you want to use.

1 Like

Got it, thank you.

This might be a good case for the switch statement too:

switch ($action) {
    case 'edit':
        $var = 'Edit';
        break;
    case 'delete':
        $var = 'Delete';
        break;
    default:
        $var = 'New';
}

On the other hand, an array of values can be used instead too.

function toProperCase(text) {
    return text.replace(/\w\S*/g, function(txt){
        return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
    });
};

$action = toProperCase($action);

var allowedActions = ['New', 'Edit', 'Delete'];
$var = allowedActions[allowedActions.indexOf($action)];
$var = $var || allowedActions[0];

Both of these examples are more readable and understandable than ternaries for this situation.

1 Like

Switch/Case statements are usually (not always) more efficient than if/else statements simply because (as I understand it) if/else statements process every instance and then choose which to insert into the DOM; whereas switch/case statements look for the condition, first, then process just the one that counts. So, yeah, I totally have to agree with @Paul_Wilkins on that. But the OP originally asked specifically about ternary operators, so I did not suggest the switch/case option.

V/r,

:slight_smile:

1 Like

For me, when you start nesting ternary operators, there is almost always a better way that’s more expressive and easier to understand.

Take for example the following code. Has a mistake been made in its logic? And how on earth would we even start to understand it?

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

Yes, it’s a bit extreme, and indenting can help a wee bit:

H = (C == 0 ? null :
    V == r ? (g - b) / C :
    V == g ? (b - r) / C + 2 :
             (r - b) / C + 4
    );
function hsbHue(color1, color2, chroma, offset) {
    return (color1 - color2) / chroma + offset;
}
var H = null;
if (C == 0) {
    return H;
}

if (V === r) {
    H = hsbHue(g, b, C, 0);
} elseif (V === g) {
    H = hsbHue(b, r, C, 2);
} else { // V must equal b
    H = hsbHue(r, g, C, 4);
}
return H;

By the way - did you notice the mistake in the ternary code? Take another look.

Is it missing the trailing semi-colons for ending each false condition?

:slight_smile:

It can be done using functions where the function returns the value to be assigned in the ternary operator - it would be rather messy though so I wouldn’t do it that way.

Consider:Wolfshades example of how not to do it

a === 'true' ? b = 1; c=2; : b = 3; c = 4; ;

to get that to work you could rewrite it as

b = (a === 'true') ? (function() {c = 2; return 1;}) : (function() { c = 4; return 3;});

Not exactly all that readable.

It could be made even shorter and less readable using the new ES6 functions

Hah! Sadly no - it’s a mistake that will cause badly calculated results.

Okay… I’ll take one more stab at it…

((r - b) / C ) + 4

Yes that’s the one - a transcription error resulted in (r - b) when it should have been (r - g), which also helps to highlight potential pitfalls of single-character variables :slight_smile:

Felgall, I like your solution!

What would be an easier to understand ternary-based way of doing this?

Perhaps as follows?

b = (a === 'true' ? 1 : 3);
c = (a === 'true' ? 2 : 4);

If you insist on using ternary operators then that would be the best way to do it. With two variables to be set that way might be reasonable although you are still testing the condition twice when using an if/else would only need to test it once. With three values to set you should definitely swap to using an if/else