是否有可能具有递归和匿名的PHP函数?这是我试图让它工作,但它不传入函数名称。匿名递归PHP函数
$factorial = function($n) use ($factorial) {
if($n <= 1) return 1;
return $factorial($n - 1) * $n;
};
print $factorial(5);
我也意识到这是一个不好的方式来实现阶乘,这只是一个例子。
是否有可能具有递归和匿名的PHP函数?这是我试图让它工作,但它不传入函数名称。匿名递归PHP函数
$factorial = function($n) use ($factorial) {
if($n <= 1) return 1;
return $factorial($n - 1) * $n;
};
print $factorial(5);
我也意识到这是一个不好的方式来实现阶乘,这只是一个例子。
为了它的工作,你需要通过$阶乘作为参考
$factorial = function($n) use (&$factorial) {
if($n == 1) return 1;
return $factorial($n - 1) * $n;
};
print $factorial(5);
+1,另请参阅http://php100.wordpress .com/2009/04/13/php-y-combinator/ – user187291 2010-03-19 20:09:15
这是奇怪的bc对象应该始终通过引用和anon传递。函数是对象... – ellabeauty 2012-08-14 21:31:46
@ellabeauty在传递$ factorial的时候,它仍然是null(未定义),这就是为什么你必须通过引用传递它。 请注意,如果您在调用函数之前修改$ factorial,那么结果会随着引用传递而改变。 – 2012-09-13 21:48:21
我知道这可能不是一个简单的办法,但我了解一个函数式语言称为"fix"技术。来自Haskell的fix
函数通常被称为Y combinator,它是最知名的fixed point combinators之一。
的固定点是,是由函数不变的值:一个函数的固定点f是任何X使得x = F(X)。固定点组合器和是为任何函数f返回固定点的函数。由于y(f)是f的不动点,我们有y(f) = f(y(f))。
本质上,Y组合器创建一个新的函数,该函数接受原始的所有参数,再加上一个附加参数即递归函数。如何使用curried表示法更加明显。不要在括号中写入参数(f(x,y,...)
),请将它们写在函数f x y ...
之后。 Y组合器定义为Y f = f (Y f)
;或者使用递归函数的单个参数Y f x = f (Y f) x
。
由于PHP并不自动curry功能,这是一个破解,使fix
工作,但我认为这很有趣。
function fix($func)
{
return function() use ($func)
{
$args = func_get_args();
array_unshift($args, fix($func));
return call_user_func_array($func, $args);
};
}
$factorial = function($func, $n) {
if ($n == 1) return 1;
return $func($n - 1) * $n;
};
$factorial = fix($factorial);
print $factorial(5);
注意这几乎是一样的单纯缝合解决方案其他人发布,但功能fix
为您创建关闭。定点组合器比使用闭包要稍微复杂一些,但更为一般,还有其他用途。虽然闭包方法更适合于PHP(这不是一种非常功能的语言),但最初的问题更多的是练习而不是生产,所以Y组合器是一种可行的方法。
值得注意的是,'call_user_func_array()'作为圣诞节是缓慢的。 – Xeoncross 2011-05-09 21:02:22
@Xeoncross与设置陆地速度记录的PHP其余部分相反? :P – 2011-05-09 21:12:49
请注意,您现在可以(5.6+)使用参数解包而不是'call_user_func_array'。 – 2017-04-17 15:43:11
虽然它不适合实际使用,但C级别扩展mpyw-junks/phpext-callee提供匿名递归而不分配变量。
<?php
var_dump((function ($n) {
return $n < 2 ? 1 : $n * callee()($n - 1);
})(5));
// 5! = 5 * 4 * 3 * 2 * 1 = int(120)
在PHP中的新版本,你可以这样做:
$x = function($depth = 0) {
if($depth++)
return;
$this($depth);
echo "hi\n";
};
$x = $x->bindTo($x);
$x();
这有可能导致奇怪的行为。
我没有PHP 5.3.0检查,但你尝试使用'全球$ factorial'? – kennytm 2010-03-19 20:02:29
*(旁注)*一个Lamba是一个匿名函数,而上面是一个闭包。 – Gordon 2010-03-19 20:21:58
Lambdas和闭包不是相互排斥的。事实上,有些人认为闭包必须是lambda,因为它是闭包(匿名函数)。例如Python你必须先给函数一个名字(取决于版本)。因为你必须给它一个名字,所以你不能内联,有人会说它不能成为一个封闭。 – 2010-05-06 13:15:02