재귀적이면서 익명인 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“라는 기술에 대해 배웠습니다.그fix
Haskell의 함수는 일반적으로 가장 잘 알려진 고정 소수점 조합기 중 하나인 Y 조합기로 알려져 있습니다.
고정점은 함수에 의해 변경되지 않는 값입니다. 함수 f의 고정점은 x = f(x)인 임의의 x입니다.고정점 결합기 y는 임의의 함수 f에 대해 고정점을 반환하는 함수이다.y(f)는 f의 고정점이므로 y(f) = f(y(f))가 됩니다.
기본적으로 Y combinator는 원래 인수와 추가 인수인 재귀 함수를 모두 포함하는 새로운 함수를 만듭니다.이것이 어떻게 작동하는지는 큐레이티드 표기법을 사용하면 더 명확하다.괄호 안에 인수를 쓰는 대신 (f(x,y,...)
), 함수 뒤에 씁니다.f x y ...
Y combinator는 다음과 같이 정의됩니다.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 combinator는 실행 가능한 접근법입니다.
실제 사용은 아니지만 C 레벨 확장 mpyw-junks/phext-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 "hin"; }; $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