Я знаю, что это может быть не простой подход, но я узнал о методике под названием «исправить» из функциональных языков. 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 - жизнеспособный подход.
global $factorial
?