匿名递归 PHP 函数

是否有可能拥有一个既递归又匿名的PHP函数?这是我尝试让它工作,但它没有传入函数名称。

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

我也意识到这是实现阶乘的坏方法,这只是一个例子。


答案 1

为了使它正常工作,您需要传递$factorial作为参考

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

答案 2

我知道这可能不是一个简单的方法,但我从函数式语言中学到了一种名为“fix”的技术。Haskell的函数通常被称为Y组合子,它是最着名的不动点组合器之一。fix

不动点是函数不变的值:函数 f 的不动点是任何 x,使得 x = f(x)。不动点组合器 y 是返回任何函数 f 的不动点的函数。由于 y(f) 是 f 的不动点,因此我们有 y(f) = f(y(f))。

从本质上讲,Y 组合器创建了一个新函数,该函数采用原始参数的所有参数,以及递归函数的附加参数。使用咖喱符号,这是如何工作的更明显。不要在括号 () 中编写参数,而是将它们写在函数之后:。Y 组合器定义为 ;或者,使用递归函数的单个参数, 。f(x,y,...)f x y ...Y f = f (Y f)Y f x = f (Y f) x

由于PHP不会自动启动函数,因此制作工作有点麻烦,但我认为这很有趣。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 );

请注意,这几乎与其他人发布的简单闭包解决方案相同,但该函数会为您创建闭包。定点组合器比使用闭包稍微复杂一些,但更通用,并且有其他用途。虽然闭包方法更适合PHP(它不是一种非常函数式的语言),但最初的问题更多的是练习而不是生产,所以Y组合器是一种可行的方法。fix


推荐