재귀 적이며 익명의 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 );
답변
나는 이것이 단순한 접근법이 아닐 수도 있다는 것을 알고 있지만, 기능 언어에서 “수정” 이라는 기술에 대해 배웠다 . fix
Haskell 의 기능은 일반적으로 가장 잘 알려진 고정 소수점 조합 중 하나 인 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);