Edit report at https://bugs.php.net/bug.php?id=64693&edit=1
ID: 64693
User updated by: jdoane at vlacs dot org
Reported by: jdoane at vlacs dot org
Summary: Third argument ($initial) passed to array_reduce
should be immutable.
Status: Not a bug
Type: Bug
Package: Arrays related
Operating System: Ubuntu 12.04.02 LTS
PHP Version: 5.3.24
Block user comment: N
Private report: N
New Comment:
So you're telling me that the inconsistent behavior is not due to the poor
implementation of array_reduce() but rather of PHP? So even though things by
name imply that a variable is immutable (hence $initial, you do know what
initial means, right?) that the resulting mutation will make it something other
than the initial value?
Thank you for clarifying that for me, but you leave me baffled as to your
reasoning why this seems like a good idea. Maybe it's not a bug, but it's
definitely not clean and consistent. Consider saying that a variable is an
"initial" value, you would think that it would remain an initial value, hence
implying the value (regardless of type) is immutable.
Previous Comments:
------------------------------------------------------------------------
[2013-04-23 15:27:11] [email protected]
array_reduce uses the normal passing semantics. We do not document for every
function that it uses the normal passing semantics, because, well, they are the
same everywhere.
PHP never clones your objects unless you tell it to.
------------------------------------------------------------------------
[2013-04-23 13:04:13] jdoane at vlacs dot org
The order of the expected output is backwards, I apologize.
It should be:
~$ php test.php
stdClass Object
(
[count] => 2
[maxlen] => 5
)
stdClass Object
(
[count] => 0
[maxlen] => 0
)
------------------------------------------------------------------------
[2013-04-22 19:41:14] jdoane at vlacs dot org
Description:
------------
When array_reduce is called with an object as the third argument, the variable
passed to said third argument will turn into the result of the array_reduce()
call. It feels like the object getting passed into array_reduce is not being
cloned and is being modified in place. Since all objects are passed as a
reference
it changes the "$initial" variable in the scope where array_reduce was called.
So either documentation needs to be updated that says that $initial gets set to
the return value when it is an object or this shouldn't happen to begin with as
it
appears that $initial should remain immutable for the duration of the
array_reduce() call.
Test script:
---------------
$array = (object)Array('foo', 'baraz');
$initial = (object)Array('count' => 0, 'maxlen' => 0);
$output = array_reduce($array, function(&$d, $item) {
if($d->maxlen < strlen($d)) { $d->maxlen = strlen($d); }
$d->count++;
return $d;
}
print_r($output);
print_r($initial);
Expected result:
----------------
~$ php test.php
stdClass Object
(
[count] => 0
[maxlen] => 0
)
stdClass Object
(
[count] => 2
[maxlen] => 5
)
Actual result:
--------------
~$ php test.php
stdClass Object
(
[count] => 2
[maxlen] => 5
)
stdClass Object
(
[count] => 2
[maxlen] => 5
)
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=64693&edit=1