首页 文章

匿名递归PHP函数

提问于
浏览
174

是否可以使用递归和匿名的PHP函数?这是我试图让它工作,但它没有传递函数名称 .

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

我也知道这是实现阶乘的一种不好的方法,它只是一个例子 .

4 回答

  • 3

    为了使其工作,您需要传递$ factorial作为参考

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

    我知道这可能不是一个简单的方法,但我从函数式语言中学到了一种名为"fix"的技术 . 来自Haskell的 fix 函数更常被称为Y combinator,它是最着名的fixed point combinators之一 .

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

    本质上,Y组合器创建一个新函数,它接受原始的所有参数,另外还有一个递归函数的附加参数 . 使用curry表示法,这是如何工作的更明显 . 而不是在括号中写入参数( 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组合器是一种可行的方法 .

  • 316

    虽然它不适用于实际用途,但C级扩展mpyw-junks/phpext-callee提供了匿名递归 without assigning variables .

    <?php
    
    var_dump((function ($n) {
        return $n < 2 ? 1 : $n * callee()($n - 1);
    })(5));
    
    // 5! = 5 * 4 * 3 * 2 * 1 = int(120)
    
  • 24

    在较新版本的PHP中,您可以这样做:

    $x = function($depth = 0) {
        if($depth++)
            return;
    
        $this($depth);
        echo "hi\n";
    };
    $x = $x->bindTo($x);
    $x();
    

    这可能会导致奇怪的行为 .

相关问题