Anonymous Recursive PHP Functions

Anonymous recursive PHP functions

In order for it to work, you need to pass $factorial as a reference

$factorial = function( $n ) use ( &$factorial ) {
if( $n == 1 ) return 1;
return $factorial( $n - 1 ) * $n;
};
print $factorial( 5 );

How to build an anonymous recursive function in PHP?

Yes you can. You need to use the $greet variable by reference, like this:

$greet = function($name) use (&$greet)
{
printf("Hello %s\r\n", $name);
if($name != 'PHP')
{
$greet('PHP');
}
};

$greet('World');

Working example:

https://3v4l.org/vUhIW

This article describes this a bit more:

https://fragdev.com/blog/php-recursion-with-anonymous-functions

Recursion with anonymous function

Yes it is, but I wouldn't recommend it as it's a bit tricky ;)

First possibility:

<?php
$some_var1="1";
$some_var2="2";
function($param1, $param2) use ($some_var1, $some_var2)
{
call_user_func(__FUNCTION__, $other_param1, $other_param2);
}
?>

Another one:

<?php 
$recursive = function () use (&$recursive){
// The function is now available as $recursive
}
?>

Examples taken from http://php.net/

Rewriting an anonymous function in php 7.4

Just like Barmar said, you can't use $f from the outside scope, because when the implicit binding takes place $f is still undefined.

There is nothing stopping you from passing it later as a parameter.

$f = fn($f, $n) => $n == 1 ? 1 : $n * $f($f, $n - 1);
echo $f($f, 5); // 120

The way arrow functions work, is that during definition time they will use by-value binding of the outer scope's variables.

As already mentioned, arrow functions use by-value variable binding. This is roughly equivalent to performing a use($x) for every variable $x used inside the arrow function. - https://wiki.php.net/rfc/arrow_functions_v2

The assignment of the closure to the variable $f happens after closure's definition and the variable $f is undefined prior to it.

As far as I am aware, there isn't any mechanism to bind by reference while defining arrow functions.

How to call the current anonymous function in PHP?

__FUNCTION__ cannot be used in anonymous functions

Pass the variable holding the anonymous function as a reference in the 'use' clause....

$f = function() use($bar, $foo, &$f) {
$f();
};

Tip of the hat to this answer.

Why must I pass as reference the anonymous function in recursive anonymous functions in PHP?

Maybe this will help:

$f = 42;
$f = function() use ($f)
{
var_dump($f);
};
$f();

That outputs 42.

The use() is hit before the function is defined and assigned to $f. So if you don't pass by reference, you are accessing the variable as it was before the function was created. In this case, 42. In your case, NULL.

By passing a reference, you'll get $f's value at the time the function is called, which will be the anonymous function as you are expecting (assuming you haven't reassigned $f).

PHP recursive function not allowing page to load

There are two problems with your code:

  • You're not including the directory for the source file in the path to subsidiary files, so those files are never found.
  • You're not returning the total from the function so that higher level invocations can add the total for subsidiary files

Correcting those issues, and renaming the variables to something meaningful gives this code:

function fileProcessor($filename){
if(file_exists(trim($filename))){
$total = 0;
$rows = file($filename, FILE_SKIP_EMPTY_LINES);
foreach($rows as $data) {
if(!preg_match("/.txt/i", $data)){
$num = floatval($data);
$total += $num;
}else {
$total += fileProcessor(dirname($filename)."/".trim($data));
}
}
echo $filename. ' - ' .($total)."<br>\n";
}else{
echo "File does not exist<br>\n";
}
return $total;
}

fileProcessor('text_files/first.txt');

Output:

text_files/third.txt - 3
text_files/second.txt - 8
text_files/first.txt - 15

This lists the files in the order in which the totals are finally accumulated, so the lowest levels appear first.

[Edit]
I spotted a problem with the order of results if two or more filenames appear in a file. Here's a reworked version that deals with that.

To list the files in the order in which they are encountered requires reversing the natural order. In the new version below I've placed the filenames in a $fileList array which is passed down by reference. Each new invocation of the function adds its results to the end of that array. Once processing is complete the array is displayed.

function fileProcessor( &$fileList){
// Get the last filename in the array
end($fileList);
$filename = key($fileList);

if(file_exists(trim($filename))){
// Accumulate the values
$fileList[$filename] = 0;
$rows = file($filename, FILE_SKIP_EMPTY_LINES);
foreach($rows as $data) {
if(!preg_match("/.txt/i", $data)){
$num = floatval($data);
$fileList[$filename] += $num;
}else {
// Recursive call. Add the next filename to the array
$fileList[dirname($filename)."/".trim($data)]=0;
$fileList[$filename] += fileProcessor($fileList);
}
}
} else {
$fileList[$filename]= "File does not exist: $filename";
}

// return the total for the file to add to the accumulator for the file above.
return $fileList[$filename];
}


// Place the initial file in the array
$results = ['text_files/first.txt' => 0];

// run the function
fileProcessor($results);

// display the results
foreach($results as $filename=>$total) {
echo $filename.' - '.$total."<br>\n";
}

Output:

text_files/first.txt - 15
text_files/second.txt - 8
text_files/third.txt - 3


Related Topics



Leave a reply



Submit