rfc:ternary_associativity

This is an old revision of the document!


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.

Future Scope

We could make the ternary right-associative, either directly in PHP 8 or at a later point in time, after it has been an error for a while. Because the current left-associative interpretation is so unlikely to be used intentionally, this is a viable change.

Vote

Straightforward Yes/No vote.

rfc/ternary_associativity.1555496391.txt.gz · Last modified: 2019/04/17 10:19 by nikic