3

The below code does not work as intended.

$fruits = array('apple', 'orange', 'banana', 'cherry');

array_walk($fruits, function($a) {
        $a= ucfirst($a);
});

var_dump($fruits);

Why does this work when we pass the reference to an individual entry in the $fruits array.

array_walk(
    $fruits, 
    function(&$a) {
        $a = ucfirst($a);
    }
);

Note: I know array_map and foreach would work, but why does array_walk() not work?.

Cœur
  • 37,241
  • 25
  • 195
  • 267
John Cooper
  • 7,343
  • 31
  • 80
  • 100
  • I don't think array_map or foreach would work, either. Unless you use references, you're not modifying the original element, you're modifying a copy. – Barmar Oct 30 '13 at 19:24
  • If a reference *isn't* used then it is [Call By Value](http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value). – user2864740 Oct 30 '13 at 19:24

4 Answers4

5

Normally PHP uses Call by Value semantics when evaluating a function. This means that reassignments to parameters will not affect variable bindings in the caller. Because of this the assignment in the "non working" code has no affect outside the callback and thus does not alter the walked array.

However, when a function parameter is specified as &.. (as discussed in Passing By Reference) the semantics switch to Call by Reference. This means that variables in the caller can be altered through reassignment of the parameters. In this case the assignment to the local parameter reassigns the currently iterated array element through Call by Reference semantics and the code "works".

Now, array_walk "works" this way because it was designed to work with Call by Reference semantics. array_map, on the other hand, uses the return value of the callback.

user2864740
  • 60,010
  • 15
  • 145
  • 220
3

If callback needs to be working with the actual values of the array, specify the first parameter of callback as a reference.

According to the docs: http://php.net/array_walk

Amal Murali
  • 75,622
  • 18
  • 128
  • 150
Shawn
  • 3,583
  • 8
  • 46
  • 63
  • @HasinHayder "The below code does not work as intended". My comment is to the first part in which he is not passing by reference... Reading the docs clearly answers his question. – Shawn Oct 30 '13 at 19:27
3

With function($a) your passing a copy of $a to the function.

With function(&$a) your passing a reference to $a to the function. This way you can alter $a from within the function.

This is why array_walk is more memory efficient that array_map; you don't need an extra variable, you apply the function to each element on the original instead of returning the newly changed array.

Related question: Difference between array_map, array_walk and array_filter

Community
  • 1
  • 1
Joren
  • 3,068
  • 25
  • 44
0

In the first example $a is local variable. All changes out of the function are lost. By the way, reference point to real array and changes it but not local copy.