I want to call an anonymous function without declaring a variable for it.
I know that this is a working example:
$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);
But I want to call and unset it automatically:
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: Let's suppose that $input
is the following array: ["Hello, ", "World!"]
.
As of that, the output should be:
Hello,
World!
Update #1:
As this is just an example, call_user_func_array(function () { ... }, $input)
is not the solution I am looking for.
And it wouldn't be working if I have an $input
like [["Hello, ", "World"], "!"]
.
Update #2:
Another solution I'm not looking for is debug_backtrace()[1]['args'][0]->__invoke($current);
. I think it is ugly enough to use for debug only. :)
Thanks to @fschmengler.
And the other form of this is call_user_func(debug_backtrace()[1]['args'][0], $current));
.
Update #3:
Another solution written by @UlrichEckhardt is embedding the anonymous function into another anonymous function. I think, unsetting the previously declared function variable - eg. first example - is both cleaner and shorter. But this is a solution too.
function () {
$f = function ($param) use ($f) {
// use $f here
}
return $f;
}()
It's possible to access the closure with debug_backtrace()
and use call it with __invoke()
to call itcall_user_func()
as before:
$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);
But in my opinion, the first version where you assign the closure to a variable is more readable and I don't see any arguments against it, other than personal taste.
Update: it has to be call_user_func()
again, not __invoke()
, so that args[0] references the closure for every level of recursion
Write a closure returning the closure you want and call that:
function () {
$f = function ($param) use ($f) {
// use $f here
}
return $f;
}()
I'm actually not convinced that PHP is capable of defining and calling a function in one step, you may have to use call_user_func()
instead to work around your language's shortcomings here. That aside, there are much better ways to write obfuscated code and if that is surprisingly not your goal, there might even be clearer alternatives. ;-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With