Saya tahu ini mungkin bukan pendekatan yang sederhana, tetapi saya belajar tentang teknik yang disebut "memperbaiki" dari bahasa fungsional. The fix
Fungsi dari Haskell dikenal lebih umum sebagai combinator Y , yang merupakan salah satu yang paling terkenal combinators titik tetap .
Titik tetap adalah nilai yang tidak diubah oleh suatu fungsi: titik tetap dari fungsi f adalah x sehingga x = f (x). Sebuah titik tetap combinator y adalah fungsi yang mengembalikan titik tetap untuk setiap fungsi f. Karena y (f) adalah titik tetap dari f, kita memiliki y (f) = f (y (f)).
Pada dasarnya, kombinator Y menciptakan fungsi baru yang mengambil semua argumen dari yang asli, ditambah argumen tambahan yang merupakan fungsi rekursif. Cara kerjanya lebih jelas menggunakan notasi curried. Alih-alih menulis argumen dalam kurung ( f(x,y,...)
), menulis mereka setelah fungsi: f x y ...
. Combinator Y didefinisikan sebagai Y f = f (Y f)
; atau, dengan argumen tunggal untuk fungsi berulang Y f x = f (Y f) x
,.
Karena PHP tidak secara otomatis menjelajah fungsi, ini sedikit hack untuk membuat fix
pekerjaan, tapi saya pikir ini menarik.
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 );
Perhatikan bahwa ini hampir sama dengan solusi penutupan sederhana yang diposkan orang lain, tetapi fungsinya fix
menciptakan penutupan untuk Anda. Combinator titik tetap sedikit lebih kompleks daripada menggunakan penutup, tetapi lebih umum, dan memiliki kegunaan lain. Sementara metode penutupan lebih cocok untuk PHP (yang bukan bahasa yang sangat fungsional), masalah asli lebih merupakan latihan daripada untuk produksi, sehingga kombinator Y adalah pendekatan yang layak.
global $factorial
?