没有声明变量的自调匿名函数

6
我想调用一个匿名函数,而不需要为其声明变量。 我知道这是可行的示例:
$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);

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


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

因此,输出应该是:

Hello, 
World!

更新 #1:

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

如果我的 $input[["Hello, ", "World"], "!"],它也无法正常工作。


更新 #2:

另一种我不想要的解决方案是 debug_backtrace()[1]['args'][0]->__invoke($current);。我认为它只够用来进行 调试。:) 感谢@fschmengler

还有另一种形式是 call_user_func(debug_backtrace()[1]['args'][0], $current));


更新 #3:

另外一种解决方案是由@UlrichEckhardt编写的,即将匿名函数嵌入到另一个匿名函数中。我认为,删除先前声明的函数变量 - 例如第一个示例 - 更加简洁、更短。但这也是一种解决方案。

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

@MichaelBerkowski (function() {...})(); 的解决方案可能很有趣,但现在并不实际。也许唯一可用的解决方案是对于 PHP 5.5 - 5.6 进行 call_user_anonym_func() 的调用。 (?) - balintant
@MichaelBerkowski 第一个例子是可行的,所以它确实可以。但我不想为函数声明一个变量并将其存储在其中(或者在完成后使用unset()删除它)。(虽然这并没有太多意义,但我认为这是一个有趣的问题。) - balintant
抱歉,抱歉。当我去搜索相关问题时,我忘记了你说顶部的示例可行。我会删除之前的评论。 - Michael Berkowski
@MichaelBerkowski 没问题!:D - balintant
在重新发明轮子之前,你是否检查过 array_walk_recursive() ?它可以遍历嵌套数组的树,并在每个叶节点上调用一个函数。 - Ulrich Eckhardt
你怎么能说取消设置匿名函数的变量会释放大量内存呢?如果你的前提假设是错误的呢?据我所知,在PHP中无法以这种方式卸载类定义。 - hakre
2个回答

4

可以使用debug_backtrace()访问闭包,然后像以前一样使用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]在每个递归级别引用闭包。


是的,这个解决方案接近我正在寻找的解决方案。但我们应该仅将其用于调试(_backtrace ...),因此我不会将其标记为我正在寻找的解决方案。谢谢! - balintant

2
编写一个返回所需闭包的闭包,并调用它:
function () {
    $f = function ($param) use ($f) {
        // use $f here
    }
    return $f;
}()

实际上,我并不认为PHP能够在一步中定义和调用函数,你可能需要使用call_user_func()来解决语言的缺陷。除此之外,有更好的方法来编写混淆代码,如果这不是你的目标,甚至可能会有更清晰的替代方案。;-)


我编写了一个名为 call_user_anonym_func() 的辅助函数,它的工作方式如下。我会尽快发布它。 :) - balintant
顺便说一下,这只是一个对我来说有趣的问题。它没有其他目标,只是想了解替代方案。 :) (如果有的话)选择最佳答案。 - balintant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接