Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the conditional operator right associative?

I can understand why the assignment operator is right associative. It makes sense that when

x = 4 + 3 

is evaluated, that 4 and 3 are added before being assigned to x.

I am unclear as to how ?: would benefit from being right associative. Does it only matter when two ?:s were used like this

z = (a == b ? a : b ? c : d); 

Then it is evaluated like this:

z = (a == b ? a : (b ? c : d)); 

Surely it would make more sense to evaluate from left to right?

like image 966
Angus Comber Avatar asked Sep 13 '11 19:09

Angus Comber


People also ask

Is conditional operator associative?

Conditional expressions have right-to-left associativity. The first operand must be of integral or pointer type. The following rules apply to the second and third operands: If both operands are of the same type, the result is of that type.

What does it mean for an operator to be right associative?

The right-associativity of the = operator allows expressions such as a = b = c to be interpreted as a = (b = c) . In C++, the assignment a = b is an expression that evaluates to the same value as the expression a , with the side effect of storing the R-value of b into the L-value of a .

Why ternary operator is right associative?

When operator + is said to be left-associative, this means that a + b + c is equivalent to (a + b) + c , as opposed to a + (b + c) . The operator = is right-associative, which means that a = b = c is equivalent to a = (b = c) , as opposed to (a = b) = c . Associativity has nothing to do with the order of evaluation.


Video Answer


2 Answers

If it evaluated from left to right, it'd look like this:

z = ((a == b ? a : b) ? c : d); 

That is, it would use the result of the first conditional (a or b) as the boolean condition of the second conditional. That doesn't make much sense: that's like saying:

int z, tmp; /* first conditional */ if(a == b) tmp = a; else       tmp = b; /* second conditional */ if(tmp) z = c; else    z = d; 

While perhaps one day you'll want to do exactly this, it's far more likely that each ?: that follows is meant to add more conditions, like if / else if / else if / else, which is what the right-associative binding yields:

int z; /* first conditional */ if(a == b)                          z = a; else /* second conditional */ if(b) z = c; else                                z = d; 
like image 186
Chris Lutz Avatar answered Sep 25 '22 21:09

Chris Lutz


In any language with a right associative ternary operator, you can stack them and build an if-elseif-elseif-else expression, like this:

val = a == 0 ? 1:       a == 1 ? 2:                4; 

On the contrary, in languages with a left associative ternary operator (such as PHP, thanks @user786653) you need to explicitly enforce the aforementioned intent with parentheses:

<?php // This will output 't', not 'true'. echo (true ? 'true' : false ? 't' : 'f');  // the following is a more obvious version of the same code as above echo ((true ? 'true' : false) ? 't' : 'f');  // here, you can see that the first expression is evaluated to 'true', which // in turn evaluates to (bool)true, thus returning the true branch of the // second ternary expression. ?> 
like image 23
Michael Foukarakis Avatar answered Sep 25 '22 21:09

Michael Foukarakis