php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75130 array_filter pass-by-ref broken
Submitted: 2017-08-28 12:11 UTC Modified: 2017-08-28 18:29 UTC
From: kernins at gmail dot com Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 7.1.8 OS: Linux x86_64
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: kernins at gmail dot com
New email:
PHP Version: OS:

 

 [2017-08-28 12:11 UTC] 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"
}


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-08-28 12:27 UTC] nikic@php.net
-Status: Open +Status: Not a bug
 [2017-08-28 12:27 UTC] 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 13:49 UTC] 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 13:51 UTC] spam2 at rhsoft dot net
http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html
 [2017-08-28 14:05 UTC] 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 18:29 UTC] kernins at gmail dot com
>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
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Apr 24 00:01:32 2024 UTC