Wiem, że to może nie być proste podejście, ale dowiedziałem się o technice zwanej „poprawką” z języków funkcjonalnych. fix
Funkcję z Haskell jest znany ogólnie jako combinator Y , który jest jednym z najbardziej znanych złożone jest ze stałą .
Punkt stały jest wartością niezmienioną przez funkcję: punktem stałym funkcji f jest dowolny x taki, że x = f (x). Kombinator punktu stałego y jest funkcją, która zwraca punkt stały dla dowolnej funkcji f. Ponieważ y (f) jest stałym punktem f, mamy y (f) = f (y (f)).
Zasadniczo kombinator Y tworzy nową funkcję, która przyjmuje wszystkie argumenty oryginału, plus dodatkowy argument, który jest funkcją rekurencyjną. Jak to działa, jest bardziej oczywiste, używając notacji curry. Zamiast pisać argumenty w nawiasach ( f(x,y,...)
), napisać je po funkcji: f x y ...
. Kombinator Y jest zdefiniowany jako Y f = f (Y f)
; lub z jednego argumentu funkcji recursed, Y f x = f (Y f) x
.
Ponieważ PHP nie działa automatycznie curry funkcji, jest trochę hack do fix
pracy, ale myślę, że to interesujące.
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 );
Pamiętaj, że jest to prawie to samo, co proste rozwiązania zamykające, które opublikowali inni, ale funkcja fix
tworzy zamknięcie dla Ciebie. Kombinatory stałoprzecinkowe są nieco bardziej złożone niż użycie zamknięcia, ale są bardziej ogólne i mają inne zastosowania. Chociaż metoda zamknięcia jest bardziej odpowiednia dla PHP (który nie jest strasznie funkcjonalnym językiem), pierwotny problem jest bardziej ćwiczeniem niż produkcją, więc kombinator Y jest realnym podejściem.
global $factorial
?