태그 보관물: recursion

recursion

익명의 재귀 PHP 함수 전달하지 않습니다. $factorial = function(

재귀 적이며 익명의 PHP 함수를 사용할 수 있습니까? 이것은 작동시키려는 시도이지만 함수 이름을 전달하지 않습니다.

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

또한 이것이 계승을 구현하는 나쁜 방법이라는 것을 알고 있습니다. 이는 단지 예일뿐입니다.



답변

작동하려면 $ factorial을 참조로 전달해야합니다.

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


답변

나는 이것이 단순한 접근법이 아닐 수도 있다는 것을 알고 있지만, 기능 언어에서 “수정” 이라는 기술에 대해 배웠다 . fixHaskell 의 기능은 일반적으로 가장 잘 알려진 고정 소수점 조합 중 하나 인 Y 결합기로 알려져 있습니다 .

고정 소수점 함수에 의해 변경되지 않은 값이다 함수의 고정 점 F는 임의이다 X 되도록 X = F (X). 고정 소수점 조합기 y 는 모든 함수 f에 대한 고정 소수점을 반환하는 함수입니다. y (f)는 고정 소수점 f이므로 y (f) = f (y (f))입니다.

기본적으로 Y 결합기는 원래의 모든 인수와 재귀 함수 인 추가 인수를 취하는 새로운 함수를 만듭니다. 이것이 작동하는 방식은 카레 표기법을 사용하여 더 분명합니다. 괄호 ( f(x,y,...))로 인수를 쓰는 대신 함수 뒤에 씁니다 f x y .... 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 );

이것은 다른 사람들이 게시 한 간단한 폐쇄 솔루션과 거의 동일하지만 함수 fix가 폐쇄를 생성합니다. 고정 소수점 조합기는 클로저를 사용하는 것보다 약간 더 복잡하지만 더 일반적이며 다른 용도로 사용됩니다. 클로저 방법은 PHP (굉장히 기능적인 언어가 아님)에 더 적합하지만, 원래 문제는 프로덕션보다 연습 문제가 더 많으므로 Y 결합기는 실행 가능한 접근법입니다.


답변

실용적이지는 않지만 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 7.1 이상에서 Y Combinator를 다음과 같이 사용할 수 있습니다.

function Y
($le)
{return
    (function ($f) 
     {return
        $f($f);
     })(function ($f) use ($le) 
        {return
            $le(function ($x) use ($f) 
                {return
                    $f($f)($x);
                });
        });
}

$le =
function ($factorial)
{return
    function
    ($n) use ($factorial)
    {return
        $n < 2 ? $n
        : $n * $factorial($n - 1);
    };
};

$factorial = Y($le);

echo $factorial(1) . PHP_EOL; // 1
echo $factorial(2) . PHP_EOL; // 2
echo $factorial(5) . PHP_EOL; // 120

그것으로 플레이 : https://3v4l.org/7AUn2

소스 코드 : https://github.com/whitephp/the-little-phper/blob/master/src/chapter_9.php


답변

변수를 정의하지 않고 익명 클래스 (PHP 7+)를 사용하는 경우 :

echo (new class {
    function __invoke($n) {
        return $n < 2 ? 1 : $n * $this($n - 1);
    }
})(5);


답변