2

I'm working on solving "A Very Big Sum" on HackerRank. The goal is to produce the sum of all the elements in an array, without using array_sum. For clarity my example code here is a little bit different than the code there.

This works:

$arr = array( 
    1000000001,
    1000000002,
    1000000003,
    1000000004,
    1000000005
);

$total = 0;
array_walk($arr, 'totalize');
echo '*' . $total;

function totalize( $arr_item ) {
    global $total;
    $total += $arr_item;
}

I'd like to avoid using a global so I can do things properly when using callback functions in the future. However, this doesn't work. I'll show the output after the code:

$arr = array( 
    1000000001,
    1000000002,
    1000000003,
    1000000004,
    1000000005
);

$total = 0;
array_walk($arr, 'totalize', $total);
echo '*' . $total;

function totalize( $arr_item, $key, &$total ) {
    $total += $arr_item;
    echo $arr_item . '.' . $key . '.' . $total . '<br />';
}

It gives this as the output:

1000000001.0.1000000001
1000000002.1.2000000003
1000000003.2.3000000006
1000000004.3.4000000010
1000000005.4.5000000015
*0

Why does the $total get added up correctly but then gets abandoned?

3
  • Either use an anonymous function and use use() or just do a simple foreach loop to go through your array and sum the values together. Commented May 3, 2016 at 18:18
  • How are namespaces related? I'm trying to learn how to pass a pointer to a function, not just solve this problem. Commented May 3, 2016 at 18:53
  • Not use, but use() for anonymous functions, there is a difference :) Commented May 3, 2016 at 19:29

2 Answers 2

5

The 3rd argument that array_walk() passes to the callback is not passed by reference, regardless of what you put in the callback's signature. For this particular case, you can use an anonymous function with the use keyword to import $total into the function's scope by reference.

$arr = [
    1000000001, 1000000002, 1000000003, 1000000004, 1000000005
];
$total = 0;
array_walk($arr, function ($arr_item) use (&$total) {
    echo ($total += $arr_item) . "\n";
});
echo '*' . $total;
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I was able to have the anonymous function pass by reference to the totalizer function. I'd show the code but it doesn't format nicely in comments. So am I correct that callbacks can't pass by reference without using an anonymous function?
If array_walk()'s callback function were set up to accept a variable by reference, no reason it wouldn't work. But it's like trying to make any built-in function accept a value by reference. If that's not how it was written, it isn't going to work.
2

The third argument of array_walk() cannot be passed as reference. When you call array_walk() it uses the value you pass as its third argument to initialize a local variable. Then it passes the local variable by reference to your callback (because this is how your callback is defined).

But there is no link between the global variable $total and the variable passed to your callback (the argument $total of totalize()). You can see this yourself if you change totalize() to also display the value of the global variable $total.

A more appropriate way to reach your goal is to use array_reduce(). The first example in the documentation is exactly the solution to your problem.

2 Comments

The callback does pass a reference. PHP core has changed in how they handle callbacks passing references. Using: array_walk($arr, 'totalize', &$total); gives the error: Fatal error: Call-time pass-by-reference has been removed in /home/quicksil/public_html/test.php on line 12
Indeed, you cannot force passing the global $total as reference to array_walk(). It copies the value it receives as its third argument, it doesn't change it. You can even pass 0 as its third argument and it still produces the same result.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.