Array function not iterating using array_shift()

Viewed 36

Below, the arrow function when called, why am I only getting the first entry?

<?php

$stack = array("orange", "banana", "apple", "raspberry");
$fruit = fn() => array_shift($stack);

var_dump($fruit());
var_dump($fruit());
var_dump($fruit());
var_dump($fruit());

Gives:

string(6) "orange"
string(6) "orange"
string(6) "orange"
string(6) "orange"

https://3v4l.org/6sTm9

1 Answers

From the manual:

A by-value binding means that it is not possible to modify any values from the outer scope

and:

Arrow functions capture variables by value automatically ... When a variable used in the expression is defined in the parent scope it will be implicitly captured by-value

Thus your function cannot modify the value of $stack, and so it returns the same value each time. To do what you want (without a parameter to the function) you need an anonymous function:

$fruit = function () use (&$stack) { return array_shift($stack); };

var_dump($fruit());
var_dump($fruit());
var_dump($fruit());
var_dump($fruit());

Output:

string(6) "orange"
string(6) "banana"
string(5) "apple"
string(9) "raspberry"

Demo on 3v4l.org

You can use an arrow function if you're willing to pass a parameter:

$stack = array("orange", "banana", "apple", "raspberry");
$fruit = fn(&$s) => array_shift($s);

var_dump($fruit($stack));
var_dump($fruit($stack));
var_dump($fruit($stack));
var_dump($fruit($stack));

Output:

string(6) "orange"
string(6) "banana"
string(5) "apple"
string(9) "raspberry"

Demo on 3v4l.org

Related