# Ternary associativity

- Thread: https://externals.io/message/111149
- Original archive: https://news-web.php.net/php.internals/111149
- Started by Nikita Popov on 2020-07-23T12:26:29+00:00
- Messages: 8
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #111149 — Nikita Popov — 2020-07-23T12:26:29+00:00

URL: https://externals.io/message/111149#111149

Hi internals,

PHP currently has an incorrect right-associative ternary operator. In
https://wiki.php.net/rfc/ternary_associativity the use of nested ternaries
was deprecated, and was supposed to become an error in PHP 8.0.

Concurrently with that proposal
https://wiki.php.net/rfc/concatenation_precedence made a very similar
change to the concatenation operator precedence. The difference here is
that this throws a deprecation notice in PHP 7.4 (same), but changes the
behavior in PHP 8.0 (rather than making it an error).

This is a pretty nonsensical outcome, in that the same type of change is
implemented in two different ways. I think it would be good to handle the
ternary change the same way as the concatenation change, i.e. make
ternaries use the correct left-associative behavior in PHP 8.0, rather than
throwing an error.

Any thoughts on that?

Regards,
Nikita

---

## #111153 — Sara Golemon — 2020-07-23T15:26:21+00:00

URL: https://externals.io/message/111149#111153 · In reply to: #111149

> PHP currently has an incorrect right-associative ternary operator. In
> https://wiki.php.net/rfc/ternary_associativity the use of nested ternaries
> was deprecated, and was supposed to become an error in PHP 8.0.
>
> Concurrently with that proposal
> https://wiki.php.net/rfc/concatenation_precedence made a very similar
> change to the concatenation operator precedence. The difference here is
> that this throws a deprecation notice in PHP 7.4 (same), but changes the
> behavior in PHP 8.0 (rather than making it an error).
>
> This is a pretty nonsensical outcome, in that the same type of change is
> implemented in two different ways. I think it would be good to handle the
> ternary change the same way as the concatenation change, i.e. make
> ternaries use the correct left-associative behavior in PHP 8.0, rather than
> throwing an error.
>
> Disagree.  Consistency is valuable, but the overlap of misusage is
different.

A stacked right-associative ternary will still give a "good" result in the
sense that it's reliably reproducible and meaningful in its output based on
being written for right-associativity.
A concat mixed with other binary ops (e.g. math ops) will NOT typically
give a "good" result since the string being contacted to the numeric then
having its math op applied will result in a nonsense answer at best.

It made sense for the concat change to favor "fixing" old code in ways that
doesn't apply to stacked-ternaries since a similar "fix" there will more
likely be a break.

Strong -1 from me.
-Sara

---

## #111159 — bjorn.x.larsson@telia.com — 2020-07-23T17:36:18+00:00

URL: https://externals.io/message/111149#111159 · In reply to: #111153

Den 2020-07-23 kl. 17:26, skrev Sara Golemon:

> 
>
> > […]
> different.
>
> A stacked right-associative ternary will still give a "good" result in the
> sense that it's reliably reproducible and meaningful in its output based on
> being written for right-associativity.
> A concat mixed with other binary ops (e.g. math ops) will NOT typically
> give a "good" result since the string being contacted to the numeric then
> having its math op applied will result in a nonsense answer at best.
>
> It made sense for the concat change to favor "fixing" old code in ways that
> doesn't apply to stacked-ternaries since a similar "fix" there will more
> likely be a break.
>
> Strong -1 from me.
> -Sara

Would it then make sense to have it as compile time error in 8.0 and
make it right-associativein in e.g. 8.1?

OTOH, when looking in RFC on top 1000 affected composer packages
it looks like having the change in 8.0 might be a way forward...

r//Björn L

---

## #111162 — twosee — 2020-07-24T11:39:03+00:00

URL: https://externals.io/message/111149#111162 · In reply to: #111149

> 2020年7月23日 下午8:26，Nikita Popov <nikita.ppv@gmail.com> 写道：
> 
> Hi internals,
> 
> PHP currently has an incorrect right-associative ternary operator. In
> https://wiki.php.net/rfc/ternary_associativity the use of nested ternaries
> was deprecated, and was supposed to become an error in PHP 8.0.
> 
> Concurrently with that proposal
> https://wiki.php.net/rfc/concatenation_precedence made a very similar
> change to the concatenation operator precedence. The difference here is
> that this throws a deprecation notice in PHP 7.4 (same), but changes the
> behavior in PHP 8.0 (rather than making it an error).
> 
> This is a pretty nonsensical outcome, in that the same type of change is
> implemented in two different ways. I think it would be good to handle the
> ternary change the same way as the concatenation change, i.e. make
> ternaries use the correct left-associative behavior in PHP 8.0, rather than
> throwing an error.
> 
> Any thoughts on that?
> 
> Regards,
> Nikita

I would rather both of them become errors
It is evil to use associativity instead of explicit parentheses
The evaluation results of these two RFCs are that the impact of these changes should be minimal and it almost always is an error, so if we want to make them consistent, why not make them all become errors?

Regards,
Twosee

---

## #111180 — Rowan Tommins — 2020-07-24T19:31:42+00:00

URL: https://externals.io/message/111149#111180 · In reply to: #111149

> PHP currently has an incorrect right-associative ternary operator. In
> https://wiki.php.net/rfc/ternary_associativity  the use of nested ternaries
> was deprecated, and was supposed to become an error in PHP 8.0.
>
> Concurrently with that proposal
> https://wiki.php.net/rfc/concatenation_precedence  made a very similar
> change to the concatenation operator precedence. The difference here is
> that this throws a deprecation notice in PHP 7.4 (same), but changes the
> behavior in PHP 8.0 (rather than making it an error).


If anything, I would argue for making both of these into errors, if 
that's possible. I think the biggest risk with this kind of change is 
not existing code relying on the old behaviour, it is code relying on 
the *new* behaviour which is accidentally run on older versions of PHP.

To give a real-life example, libraries that supported PHP 5.3 sometimes 
received patches containing the short array syntax introduced in 5.4. 
Since few projects have perfect test coverage and CI builds against 
multiple targets, these might end up in tagged releases. They were soon 
spotted by 5.3 users, because they caused a fatal error.

A similar mistake involving concatenation or ternary precedence (with 
code tested on 8.x and run on 7.x) would lead to much subtler bugs, and 
might go undetected for longer.

I realise that I am advocating an extra delay here, where I just argued 
the opposite regarding named parameters. I think the cost-benefit 
analysis comes out differently, notably on the benefit side:

- raising an error has significant benefits over the current behaviour, 
since it makes mistakes easier to spot
- the remaining benefit of the full change is only a mild convenience, 
since the behaviour can be achieved by adding parentheses

Regards,

-- 
Rowan Tommins (né Collins)
[IMSoP]

---

## #111183 — Chuck Adams — 2020-07-25T15:26:09+00:00

URL: https://externals.io/message/111149#111183 · In reply to: #111180

> If anything, I would argue for making both of these into errors, if
> that's possible. I think the biggest risk with this kind of change is
> not existing code relying on the old behaviour, it is code relying on
> the *new* behaviour which is accidentally run on older versions of PHP.

I thought the proposal to turn unparenthesized use into a warning then
waiting for PHP9 to use the proper precedence was the right idea.
Nested ternaries with the proper precedence turn into lovely truth
tables, which isn't even an uncommon idiom in C.  I'd really not like
to feed /r/lolphp ammo by requiring the parens in all cases and
continuing to break the ternary operator in comparison with every
other language that has it.

--c

---

## #111185 — Rowan Tommins — 2020-07-25T15:48:29+00:00

URL: https://externals.io/message/111149#111185 · In reply to: #111183

> 
>
> > […]
> I thought the proposal to turn unparenthesized use into a warning then
> waiting for PHP9 to use the proper precedence was the right idea.
> Nested ternaries with the proper precedence turn into lovely truth
> tables, which isn't even an uncommon idiom in C.  I'd really not like
> to feed /r/lolphp ammo by requiring the parens in all cases and
> continuing to break the ternary operator in comparison with every
> other language that has it.


I think we're talking at cross-purposes here; I'm not saying it should 
throw an error forever, I'm saying it should throw an error in PHP 8.x, 
and have new behaviour in 9.x, which as I understand it is the current 
plan.

Nikita is suggesting that it should instead change behaviour immediately 
in PHP 8.x, so that the below code would be valid in both PHP 7.4 and 
8.0, but with a different outcome:

$enableFoo =
    $config['foo']['enabled'] ? true
    : $config['foo']['disabled'] ? false
    : $config['default_enabled'] ? true
    : false;

I think there is too high a risk that a library would include that code 
intending the new behaviour, while claiming support for PHP 7.x, thus 
introducing a subtle and confusing bug.


The same risk applies to the concatenation case Nikita mentioned, which 
concerns code like this:

$priceLabel = $currencySymbol . $price + $tax;

Since PHP 7.4 detects the affected situations and raises an 
E_DEPRECATED, I think it would be safer to detect them and throw an 
error in PHP 8.x, rather than immediately changing behaviour.


In both cases, the correct behaviour can safely be added in PHP 9.0, 
since it's incredibly unlikely that code will be run on both 9.0 and 
7.x, but never on 8.x


Regards,

-- 
Rowan Tommins (né Collins)
[IMSoP]

---

## #111187 — Andrea Faulds — 2020-07-25T17:01:48+00:00

URL: https://externals.io/message/111149#111187 · In reply to: #111159

Hey,

Björn Larsson wrote:
> 
> Would it then make sense to have it as compile time error in 8.0 and
> make it right-associativein in e.g. 8.1?
> 
> OTOH, when looking in RFC on top 1000 affected composer packages
> it looks like having the change in 8.0 might be a way forward...
> 
> r//Björn L

I think 7.4 and 8.1 are too close to eachother, only two versions apart. 
There's probably a lot of people out there who don't upgrade PHP version 
yearly, so they might write 7.4 code and then hop over to 8.1, and oops, 
it's silently broken!

I see other threads suggesting changing in 9.x which seems less 
problematic, I guess.

Regards,
Andrea
