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
Read Each Line of Txt File to New Array Element
Convert Timestamp to Readable Date/Time PHP
Super Fast Getimagesize in PHP
How to Validate Google Recaptcha V3 on Server Side
Why Does the PHP Json_Encode Function Convert Utf-8 Strings to Hexadecimal Entities
Intl Extension: Installing PHP_Intl.Dll
"Vertical" Regex Matching in an Ascii "Image"
How to Get the Current Page'S Full Url on a Windows/Iis Server
Can You Store a Function in a PHP Array
How to Embed Youtube Videos in PHP
PHP How to Get Local Ip of System
Sending Multiple Iphone Push Notifications + Apns + PHP
Calculate Age Based on Date of Birth
PHP: Check If an Array Contains All Array Values from Another Array