无法将递归函数转换为 IIFE

Cannot convert a recursive function into an IIFE

我有一个代码包含这样的递归函数:

<?php

$arr = [];

function recursive(&$argument)
{
    if (count($argument) < 10)
    {
        $argument[] = 'foo';
        recursive($argument);
    }
}
recursive($arr);

print_r($arr);

?>

效果很好。但是在我将递归函数转换为 IIFE(立即调用函数表达式)后开始出现错误,如下所示:

$recursive = (function (&$argument)
{
    if (count($argument) < 10)
    {
        $argument[] = 'foo';
        $recursive($argument);    // line 10
    }
})($arr);

错误是:

Notice: Undefined variable: recursive in php_file_path on line 10

Fatal error: Uncaught Error: Function name must be a string in php_file_path:10

Stack trace:

#0 php_file_path(12): {closure}(Array)

#1 {main}

thrown in php_file_path on line 10

我想可能是函数需要引用自身的变量,所以我加了关键字use,如下。但是结果的错误没有区别,除了未定义变量的通知现在指向第5行。

$recursive = (function (&$argument) use ($recursive)    // line 5
{
    if (count($argument) < 10)
    {
        $argument[] = 'foo';
        $recursive($argument);
    }
})($arr);

请注意,代码只是为了说明起见的示例。

我不清楚你想在这里实现什么,但你可以使用 global 语句在函数中定义 $recursive 来实现你想要做的事情:

$arr = array();
($recursive = function (&$argument)
{
    global $recursive;

    if (count($argument) < 10)
    {
        $argument[] = 'foo';
        $recursive($argument);    // line 10
    }
})($arr);
print_r($arr);

输出:

Array
(
    [0] => foo
    [1] => foo
    [2] => foo
    [3] => foo
    [4] => foo
    [5] => foo
    [6] => foo
    [7] => foo
    [8] => foo
    [9] => foo
)

Demo on 3v4l.org

注意调用前需要将$arr定义为空数组,否则count会失败。如果您不想这样做,则需要在函数中包含一个 if (empty($arr)) 检查。

另请注意,$recursive 可用于此语句后的其余代码,例如

$arr2 = array();
$recursive($arr2);

这是更传统的 PHP 方式:

$recursive = function (&$argument)
{
    global $recursive;

    if (count($argument) < 10)
    {
        $argument[] = 'foo';
        $recursive($argument);    // line 10
    }
};
$arr = array();
$recursive($arr);
print_r($arr);

输出相同。 Demo on 3v4l.org

更新

进一步观察,显然可以使用 use 而不是 global,通过在 use 表达式中使用 &$recursive,使它是一个参考而不是一个直接值。例如:

$arr = array();
($recursive = function (&$argument) use (&$recursive)
{
    if (count($argument) < 10)
    {
        $argument[] = 'foo';
        $recursive($argument);    // line 10
    }
})($arr);
print_r($arr);

$recursive = function (&$argument) use (&$recursive)
{
    if (count($argument) < 10)
    {
        $argument[] = 'foo';
        $recursive($argument);    // line 10
    }
};
$arr = array();
$recursive($arr);
print_r($arr);

Demo on 3v4l.org