自动调用匿名函数而不声明为变量

时间:2015-02-01 13:48:27

标签: php recursion anonymous-function php-5.5

我想调用一个匿名函数而不为它声明一个变量。

我知道这是一个有效的例子:

$foo = function ($bar) use ($foo) {
    if (is_array($bar)) {
        foreach ($bar AS $current) {
             $foo($current);
        }
    }
    else {
        print($bar);
    }
};

$foo($input);

# Unset variable cause we won't need it anymore
# and we like to have a lot of free memory.
unset($foo);

但我想自动调用并取消设置:

call_user_func(function ($bar) {
    if (is_array($bar)) {
         foreach ($bar AS $current) {
             # This won't work
             # as our function doesn't have any name.
             call_user_func(__FUNCTION__, $current);
         }
    }
    else {
         print($bar);
    }
}, $input);

但是这个例子不起作用,因为我们的函数没有名字。有没有解决方案,或者你知道解决这个问题的任何解决方案吗?


PS:我们假设$input是以下数组:["Hello, ", "World!"]

此时,输出应为:

Hello, 
World!

更新#1:

由于这只是一个例子,call_user_func_array(function () { ... }, $input)不是我要找的解决方案。

如果我有一个$input [["Hello, ", "World"], "!"],它将无法正常工作。


更新#2:

我认为仅仅用于 debug 是非常丑陋的。 :) 感谢@fschmengler

另一种形式是debug_backtrace()[1]['args'][0]->__invoke($current);


更新#3:

@UlrichEckhardt编写的另一个解决方案是将匿名函数嵌入到另一个匿名函数中。我认为,取消先前声明的函数变量 - 例如。第一个例子 - 更清洁,更短。但这也是一个解决方案。

call_user_func(debug_backtrace()[1]['args'][0], $current));

2 个答案:

答案 0 :(得分:4)

可以使用debug_backtrace()访问闭包,使用__invoke()来调用它像以前一样用call_user_func()调用它:

$input = ["Hello, ", "World!"];

call_user_func(function ($bar) {
    if (is_array($bar)) {
         foreach ($bar AS $current) {
             call_user_func(debug_backtrace()[1]['args'][0], $current));
         }
    }
    else {
         print($bar);
    }
}, $input);

但是在我看来,将闭包赋值给变量的第一个版本更具可读性,除了个人品味之外,我没有看到任何反对它的论据。

更新:它必须再次call_user_func(),而不是__invoke(),以便args [0]引用每个递归级别的闭包

答案 1 :(得分:2)

写一个闭包返回你想要的闭包并调用:

function () {
    $f = function ($param) use ($f) {
        // use $f here
    }
    return $f;
}()

我实际上不相信PHP能够在一个步骤中定义和调用函数,您可能必须使用call_user_func()来解决您的语言缺点。除此之外,还有更好的方法来编写混淆的代码,如果令人惊讶的是不是你的目标,那么甚至可能有更清晰的替代方案。 ; - )