Самозвонящая анонимная функция без объявления в качестве переменной

Я хочу вызвать анонимную функцию, не объявляя переменную для нее.

Я знаю, что это рабочий пример:

$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_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;
}()

6

Решение

Доступ к закрытию возможен с 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] ссылается на замыкание для каждого уровня рекурсии

4

Другие решения

Напишите закрытие, возвращающее желаемое закрытие, и назовите это:

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

Я на самом деле не уверен, что PHP способен определять и вызывать функцию за один шаг, возможно, вам придется использовать call_user_func() вместо этого, чтобы обойти недостатки вашего языка здесь. Помимо этого, есть гораздо лучшие способы написания запутанного кода, и, если это не является вашей целью, могут быть даже более ясные альтернативы. 😉

2