Anonim özyinelemeli PHP fonksiyonları

3 Cevap php

Özyinelemeli ve anonim hem de bir PHP işlevi olması mümkün mü? Bu işe almak için benim girişimi olduğunu, ancak bu işlev adı geçmez.

$factorial = function( $n ) use ( $factorial ) {
    if( $n <= 1 ) return 1;
    return $factorial( $n - 1 ) * $n;
};
print $factorial( 5 );

Ben de bu çarpınımını uygulamak için kötü bir yol olduğunu farkında değilim, bu sadece bir örnek.

3 Cevap

Bu çalışması için, bir referans olarak $ çarpınımını geçmek gerekir

$factorial = function( $n ) use ( &$factorial ) {
    if( $n == 1 ) return 1;
    return $factorial( $n - 1 ) * $n;
};
print $factorial( 5 );

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.

Bu (küresel kullanır) deneyin:

 $factorial = function($n) {
   global $factorial;
   if ($n == 1) return 1;
   return $factorial($n - 1) * $n;
 };

ya da (create_function ve yorumsuz metin kullanarak)

 $factorial = create_function('$n', <<<'EOL'
   global $factorial; 
   if( $n == 1 ) return 1;
   return $factorial($n - 1) * $n;
   EOL
 );