caijw
caijw

Reputation: 35

Order of execution for functions on either side of the assignment operator

I want to implement a function

$input = ['key1', 'value1', 'key2', 'value2'];
// $output = ['key1' => 'value1', 'key2' => 'value2'];
$output=[];
do {
    $output[current($input)] = next($input);
} while (next($input));

I wrote this code intuitively, but when I reviewed this code today, I pondered if this might be a bug.

I assumed the output should be something like this:

['value1'=>'value1','value2'=>'value2']

because next() takes precedence over current(), but this function works fine in PHP8.

Why is this? Isn't assignment from right to left?

Upvotes: -2

Views: 105

Answers (2)

Nisse Engström
Nisse Engström

Reputation: 4751

Operator precedence and associativity, and order of evaluation are different things. The first two tell you how to interpret an expression, i.e. x() - y() - z() means (x() - y()) - z(), but they don't tell you in which order each operand will be evaluated.

The PHP documentation on Operator Precedence says (emphasis added):

Operator precedence and associativity only determine how expressions are grouped, they do not specify an order of evaluation. PHP does not (in the general case) specify in which order an expression is evaluated and code that assumes a specific order of evaluation should be avoided, because the behavior can change between versions of PHP or depending on the surrounding code.

I ran a couple of tests on PHP 8.3.10 and in this case the functions are evaluate Left-to-Right regardless of associativity.

Example Left-to-Right

<?php

function f1 () { echo "f1"; return 1; }
function f2 () { echo "f2"; return 1; }

$v = f1() + f2(); /* Left-to-Right */

echo "\n"; /* Output: f1f2 */

Example Right-to-Left

<?php

function f1 () { echo "f1"; return 1; }
function f2 () { echo "f2"; return 1; }

$v = f1() ** f2(); /* Right-to-Left */

echo "\n"; /* Output: f1f2 */

See also a Example 2 in the PHP documentation:

$i = 1;
$array[$i] = $i++; // may set either index 1 or 2

Upvotes: 0

nice_dev
nice_dev

Reputation: 17825

The associativity is from left to right for = for your case. You can cross check this with the below snippet where t1 gets printed first instead of t2.

<?php

$output=[];

$output[test('t1')] = test('t2');

function test($str){
    echo $str,PHP_EOL;
    return rand(10, 100);
}

Demo

Hence, your output is [ 'key1' => 'value1','key2' => 'value2'] because current() gives key1 and next() advances the internal array pointer and returns the element value which is value1 and the same gets repeated over until the array is looped completely.

Upvotes: 2

Related Questions