rfc:ternary_associativity

PHP RFC: Deprecate left-associative ternary operator

Introduction

Unlike most (all?) other languages, the ternary operator in PHP is left-associative rather than right-associative. The left-associative behavior is generally not useful and confusing for programmers who switch between different languages. This RFC proposes to deprecate and remove left-associativity for the ternary operator and require explicit use of parentheses instead.

As an example, the code

return $a == 1 ? 'one'
     : $a == 2 ? 'two'
     : $a == 3 ? 'three'
     : $a == 4 ? 'four'
               : 'other';

would in most (all?) other languages be interpreted as

return $a == 1 ? 'one'
     : ($a == 2 ? 'two'
     : ($a == 3 ? 'three'
     : ($a == 4 ? 'four'
               : 'other')));

which is both the useful and intuitive interpretation. In PHP, it is instead interpreted as

return ((($a == 1 ? 'one'
     : $a == 2) ? 'two'
     : $a == 3) ? 'three'
     : $a == 4) ? 'four'
               : 'other';

which is generally not what was intended.

Proposal

In PHP 7.4 using nested ternaries without explicit parentheses will throw a deprecation warning. In PHP 8.0 it will become a compile-time error instead.

1 ? 2 : 3 ? 4 : 5;   // deprecated
(1 ? 2 : 3) ? 4 : 5; // ok
1 ? 2 : (3 ? 4 : 5); // ok

This also applies when mixing short and long ternary syntax:

1 ?: 2 ? 3 : 4;   // deprecated
(1 ?: 2) ? 3 : 4; // ok
1 ?: (2 ? 3 : 4); // ok
 
1 ? 2 : 3 ?: 4;   // deprecated
(1 ? 2 : 3) ?: 4; // ok
1 ? 2 : (3 ?: 4); // ok

However, as an exception, explicit parenthesis are not required when combining two short ternaries:

1 ?: 2 ?: 3;   // ok
(1 ?: 2) ?: 3; // ok
1 ?: (2 ?: 3); // ok

The reason is that ($a ?: $b) ?: $c and $a ?: ($b ?: $c) will always yield the same result, even though the left-associative version will arrive at it in a less efficient manner.

Parentheses are also not required when nesting into the middle operand, as this is always unambiguous and not affected by associativity:

1 ? 2 ? 3 : 4 : 5 // ok
1 ? 2 ?: 3 : 4    // ok

The null-coalesce operator ?? is already right-associative and not affected by these changes.

Backward Incompatible Changes

Code exploiting left-associativity of the ternary operator will become a hard error in PHP 8. As left-associative ternaries are almost certainly bugs, the impact of this change should be minimal.

An analysis of the top 1000 composer packages found 12 instances that will be affected by this RFC. 9 of them are bugs, where a right-associative meaning was intended, but a left-associative one will be used. 3 uses of the form $a ? $b : $c ?: $d are potentially okay, because the difference between the two interpretations is small and it's not obvious to me which one is actually intended. Detailed analysis results are available at https://gist.github.com/nikic/b6214f87b0e4a7c6fe26919ac849194f.

Future Scope

We could make the ternary right-associative in a later release, after it has been an error for a while.

Vote

Voting started 2019-04-23 and ends 2019-05-07.

Deprecate and remove left-associative ternary without explicit parentheses?
Real name Yes No
andrey  
ashnazg  
bishop  
bwoebi  
carusogabriel  
derick  
didou  
diegopires  
duncan3dc  
emir  
galvao  
girgias  
guilhermeblanco  
jasny  
jbnahan  
jhdxr  
kalle  
kelunik  
kinncj  
levim  
malukenho  
marcio  
mariano  
mbeccati  
mcmic  
mike  
nikic  
ocramius  
patrickallaert  
petk  
pmmaga  
pollita  
rasmus  
reywob  
salathe  
santiagolizardo  
sebastian  
sergey  
stas  
trowski  
weierophinney  
yohgaki  
yunosh  
zeev  
zimt  
Final result: 35 10
This poll has been closed.
rfc/ternary_associativity.txt · Last modified: by 127.0.0.1