Bug #75130 [Nab]: array_filter pass-by-ref broken
| From: | kernins at gmail dot com | Date: | Mon, 28 Aug 2017 18:30:00 +0000 |
| Subject: | Bug #75130 [Nab]: array_filter pass-by-ref broken | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-210857@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=75130&edit=1
ID: 75130
User updated by: kernins at gmail dot com
Reported by: kernins at gmail dot com
Summary: array_filter pass-by-ref broken
Status: Not a bug
Type: Bug
Package: Arrays related
Operating System: Linux x86_64
PHP Version: 7.1.8
Block user comment: N
Private report: N
New Comment:
>the ability to perform modifications inside a function called "filter", which is a
>very well-defined functional programming construct that certainly does not include mutability,
>somewhat defeats the purpose of having a well-delineated functional processing pipeline
Well, that makes perfect sense. Agreed
Previous Comments:
------------------------------------------------------------------------
[2017-08-28 14:05:05] nikic@php.net
> First of all, it worked the whole 5.x series and I have a lot of code using it that way. Such
> usage was considered valid before => BC break here.
Sure. It's a BC break in a semver-major release fixing a bug in the previous implementation.
> This will result in two loops instead of one => performance hit on large arrays (even if it
> is negligible, it is still here) and less compact code.
If you are interested in performance, using array_filter() and similar is already a losing
proposition. The most efficient way to perform any kind of loop-based operation is a foreach() loop.
People use functions like array_map() or array_filter() not for reasons of performance, but for
reasons of clarity. It goes without saying that the ability to perform modifications inside a
function called "filter", which is a very well-defined functional programming construct
that certainly does not include mutability, somewhat defeats the purpose of having a well-delineated
functional processing pipeline.
$arr = array_map('strtoupper', array_filter($arr, 'strlen'));
> Why the hell one array_* functions are working with refs, while the others shouldn't? This
> at least adds even more inconsistency to already inconsistent php api.
Because some functions operate in-place, while others return new arrays. Functions operating
in-place (array_walk, sort, shuffle) accept by-reference, while nearly all other functions
(array_map, array_filter) do not operate in-place and accept by-value.
------------------------------------------------------------------------
[2017-08-28 13:51:34] spam2 at rhsoft dot net
http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html
------------------------------------------------------------------------
[2017-08-28 13:49:20] kernins at gmail dot com
First of all, it worked the whole 5.x series and I have a lot of code using it that way. Such usage
was considered valid before => BC break here.
2nd
>The correct way to write this code is a combination of array_map and array_filter.
This will result in two loops instead of one => performance hit on large arrays (even if it is
negligible, it is still here) and less compact code.
3rd
Why the hell one array_* functions are working with refs, while the others shouldn't? This at
least adds even more inconsistency to already inconsistent php api.
So, this IS a bug
------------------------------------------------------------------------
[2017-08-28 12:27:42] nikic@php.net
If a function doesn't explicitly document that it's operating on references (such as
array_walk), then you can generally assume that it does not work with references.
The correct way to write this code is a combination of array_map and array_filter.
------------------------------------------------------------------------
[2017-08-28 12:11:52] kernins at gmail dot com
Description:
------------
Passing array element to callback by ref doesn't work anymore, resulting array contains
original/unmodified values
Test script:
---------------
$arr=['foo', 'bar', '', 'baz'];
$arr=array_filter($arr, function(&$el){
$el=strtoupper($el);
return strlen($el)>0;
});
var_dump($arr);
Expected result:
----------------
array(3) {
[0]=>
string(3) "FOO"
[1]=>
string(3) "BAR"
[3]=>
string(3) "BAZ"
}
Actual result:
--------------
array(3) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
[3]=>
string(3) "baz"
}
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=75130&edit=1