Bug #75130 [Nab]: array_filter pass-by-ref broken

From: 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

« previous php.bugs (#210857) next »