php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #81511 Evaluation order for . operator should be specified
Submitted: 2021-10-07 06:56 UTC Modified: 2021-10-07 22:26 UTC
From: dean at omnivisiontechnology dot com Assigned:
Status: Not a bug Package: Unknown/Other Function
PHP Version: Irrelevant OS: n/a
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: dean at omnivisiontechnology dot com
New email:
PHP Version: OS:

 

 [2021-10-07 06:56 UTC] dean at omnivisiontechnology dot com
Description:
------------
---
From manual page: https://php.net/language.operators.string
---

In general, PHP doesn't specify the order of evaluation for operators.
However, order of evaluation for the string concatenation operator specifically,  does always seem to be left then right.

If this can indeed be guaranteed, then it should be specified in the documentation, because it enables the very common coding idiom:

$string = 'something'.($complicatedSubstring = 'something else').'more stuff'.$complicatedSubstring;

Test script:
---------------
$s = '[Very bad!]'
$x = 'bar '.($s = 'foo').' bar bar '.$s.' bar';

 

Expected result:
----------------
$x should be 'bar foo bar bar foo bar'.
It'd be very unexpected for it to be 'bar foo bar bar [Very bad!] bar',
But that's what could happen if the . operator evaluated the RHS first... which fortunately it doesn't appear to.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-10-07 08:26 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2021-10-07 08:26 UTC] requinix@php.net
It isn't specified because it isn't guaranteed. It's generally left to right, sure, but the exact behavior may change in the future if PHP alters how it parses and executes code. Not guaranteeing behavior also potentially allows caching or optimization extensions more freedom in the benefits they can offer.

It's a bad idiom. Don't use it. "Clever" code doesn't benefit anyone.
 [2021-10-07 10:25 UTC] dean at omnivisiontechnology dot com
If evaluation order might change, then there's nothing to be done.

But I'd note that "clever" or not, this idiom can be very useful in writing concise code, for example buried deep inside nested ternaries, where you can only put an expression and not a statement block, e.g.

$s = ($a ? "option A" : ($b ? "Option B" : ($c ? "Option C" : 'Value is: '.($v = expensiveFunction())." other stringy stuff ".$v)));

vs

if (!($a||$b||$c)) $v = expensiveFunction();
$s = ($a ? "option A" : ($b ? "Option B" : ($c ? "Option C" : 'Value is: '.$v." other stringy stuff ".$v)));

which apart from being longer, also contains the same condition check in two places (and in two different formats), leading to potential bugs if one is changed and the other is not.
 [2021-10-07 18:04 UTC] requinix@php.net
if ($a) {
  $s = "option A";
} else if ($b) {
  $s = "option B";
} else if ($c) {
  $s = "option C";
} else {
  $v = expensiveFunction();
  $s = "Value is: {$v} other stringy stuff {$v}";
}
 [2021-10-07 22:26 UTC] dean at omnivisiontechnology dot com
Well obviously.  But I did say *concise* code!

Also I rather suspect there's lots of code like my example out in the wild, which would break if the . operator didn't evaluate LHS first.
You read strings left-to-right (in most languages), so psychologically I think programmers expect and assume it's going to work that way, much more than for other (non-string) operators.
 [2021-10-08 00:36 UTC] a at b dot c dot de
Why call out string concatenation especially? This "very common coding idiom" (which I've never seen before and hope to never see again) would be equally applicable with any other associative operator. If it is "guaranteed" for one then people will expect the same guarantees for the others as well.

Tangentially, it is already the case that concatenation isn't strictly left-to-right: currently the concatenations in "$x = $x . $t . $v" aren't done in the same order as those in "$x .= $t . $v". Obviously it's because assignment operators have lower precedence, but the equivalency of the two relies on the expectation is that evaluation order shouldn't matter for associative operators. And string concatenation is generally regarded as an associative operator.

"Concise" is not a goal in itself. "Readable" is more important.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Apr 29 07:01:30 2024 UTC