Ben bu basit bir yaklaşım olmayabilir biliyorum, ama ben fonksiyonel dillerden denilen bir teknikle "fix" öğrendim. Haskell'e gelen fix
fonksiyonu en iyi bilinen biri olan, Y combinator olarak daha genel olarak da bilinir fixed point combinators.
Bir sabit nokta bir fonksiyonu değişmeden bir değerdir: Bir fonksiyonun bir sabit nokta f herhangi bir x şekilde x = f (x). Sabit bir nokta combinator y, herhangi bir fonksiyon f için bir sabit nokta döndüren bir fonksiyondur. Y (f) f sabit bir nokta olduğu için, Y (f) = f (y (f)) sahiptir.
Esasen, Y combinator tüm orijinal argümanlar, artı özyinelemeli fonksiyon bulunuyor ek bir argüman alan yeni bir işlev oluşturur. Bu nasıl çalışır Curried notasyonu kullanarak daha fazla açıktır. Bunun yerine parantez içinde yazılı argümanlar (f(x,y,...)
), işlevi sonra bunları yazmak: f x y ...
. Y combinator Y f = f (Y f)
gibi tanımlanmıştır; veya, recursed fonksiyonu için tek bir argüman ile, Y f x = f (Y f) x
.
PHP otomatik olarak değil curry fonksiyonları yapar beri, bu bir hack biraz fix
iş yapmak, ama ben ilginç olduğunu düşünüyorum.
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 );
Bu neredeyse diğerleri gönderdiniz basit kapama çözümü aynıdır, ancak fonksiyon fix
sizin için kapatma oluşturur. Sabit nokta combinators biraz daha karmaşık bir kapatma kullanarak daha vardır, fakat daha geneldir, ve diğer anlamları var. Kapatma yöntemi PHP (korkunç işlevsel bir dil değil) için daha uygun olsa da, orijinal sorun üretimi için daha bir egzersiz fazla, yani Y combinator uygulanabilir bir yaklaşımdır.