2010-11-11 7 views
2

Existe-t-il un truc en PHP 4 pour implémenter des fonctions qui renvoient des fonctions? Je pensais que le code suivant fonctionnerait:Fonctions anonymes (lambdas, fermetures) en PHP 4

function xxx($a) { 
    return function($b) { 
    print "a=$a, b=$b \n"; 
    } 
} 

$f1 = xxx(1); 
$f1(2); 

Malheureusement, pas de chance en PHP 4. Probablement cela fonctionne en PHP 5, mais je me suis limité à PHP 4.

J'ai essayé de contourner avec OO, mais à nouveau échoué (déclarations de classe ne peuvent pas être imbriquées):

class Closure { 
    function run($a) { 
    print "raise: NotImplementedException, instead: $a\n"; 
    } 
} 

class WantCheckNesting extends Closure { 
    function run($a, $b) { 
    class Nested extends Closure { 
     function run($c) { 
     print "a=$a, b=$b, c=$c\n"; 
     } 
    } 
    $o = new Nested(); 
    return $o; 
    } 
} 

$d = new WantCheckNesting(); 
$e = $d->run(2, 3); 
$e->run(4); 

il y a une fonction « create_function », mais il est très limité: le corps doit être une chaîne.

D'autres idées?

Répondre

4

Vous aboyez probablement au mauvais arbre. PHP n'est pas un langage de programmation fonctionnel. Certains changes ont été créés à partir de PHP 5.3, mais même là vous n'avez pas vos étendues de variables attendues qui vous permettraient de faire ce que vous avez dans vos exemples.

Les seuls outils que vous pouvez utiliser dans PHP 4 sont create_function et un peu d'ingéniosité pour écrire la définition de la fonction sous forme de chaîne.

<?php 

function getMyFunc($a){ 
    return create_function('$b', 'print "a='.$a.', b=$b";'); 
} 

$f1 = getMyFunc(1); 
$f1(2); 

?> 

... mais même si cela est simple pour votre exemple, il n'est certainement pas pratique pour des situations plus complexes.

0

En PHP4, vous pouvez utiliser les fonctions variables comme ceci, à condition que votre fonction soit déjà définie dans la portée (donc pas une fermeture réelle).

CECI EST CODE SALE. CE N'EST PAS BEAUCOUP TESTÉ. CE N'EST PAS RAPIDE (encore plus lent que les fermetures si c'est possible). C'est juste pour le plaisir et pour prouver que "d'une manière ou d'une autre" peut être fait si vous en avez vraiment vraiment besoin.

Nécessite un répertoire tmp/accessible en écriture.

<?php 
    function xxx($a) { 
     $sid = GetUniversalSessionId(); 
     $tmpfname= 'tmp/'.$sid.'.php'; 

     $handle = fopen($tmpfname, "w"); 
     fwrite($handle, '<?php 
     function func_'.($sid).'($b) { 
      $a='."'".str_replace("\'","\\'",str_replace("\\","\\\\",$a))."'".'; 
      print "a=$a, b=$b \n"; 
     } 
    ?>'); 
     fclose($handle); 
     include($tmpfname); 
     unlink($tmpfname); 

     return 'func_'.($sid); 
    } 


    $result=xxx(32); 

    $result(20); 







    // This is just to get a unique identifier for every connection and every function call: 
    // UNIVERSALSESSIONIDS v1.3 

    if(defined('UNIVERSALSESSIONIDS')) return; 
    define('UNIVERSALSESSIONIDS', TRUE); 




    function GetTimeStart() { 
     return strtotime('2006-07-10'); 
    } 

    function GetUniversalSessionId() { 
     return GetCodedSid(letterNumBase(),16); 
    } 
    function GetCodedSid($baseChars,$Pad=0) { 
     $Zero=$baseChars{0}; 
     list ($usec, $sec) = explode (' ', microtime()); 
     $new_sid = ($sec-GetTimeStart()) . str_pad ((int)($usec * 100000000), 8, '0', STR_PAD_LEFT) . str_pad (rand (0, 9999), 4, '0', STR_PAD_LEFT); 

     $new_sid=ConvertDecToAnyStr($new_sid,$baseChars); 
     $new_sid=str_pad ($new_sid, $Pad, $Zero, STR_PAD_LEFT); 
     return $new_sid; 
    } 

    function divide($decstr,$decnum) { 
     $Start=''; 
     $Result=''; 
     $WRITE=FALSE; 
     do { 
      $Start.=substr($decstr,0,1); 
      $decstr=substr($decstr,1); 

      $DecStart=intval($Start); 

      $Rest=$DecStart%$decnum; 
      $PartDiv=($DecStart-$Rest)/$decnum; 
      if($PartDiv>0) $WRITE=TRUE; 

      if($WRITE) $Result.=$PartDiv; 
      $Start=$Rest; 

     } while ($decstr!=''); 
     if($Result=='') $Result='0'; 
     return array($Result,$Rest); 
    } 

    function bigBase() { 
     global $gSavedBigBase; 

     if(isset($gSavedBigBase)) return $gSavedBigBase; 
     $BigBase=''; 
     for($i=33;$i<=128;$i++) $BigBase.=chr($i); 
     $gSavedBigBase=$BigBase; 
     return $BigBase; 
    } 

    function letterNumBase() { 
     global $gSavedBigBase2; 

     if(isset($gSavedBigBase2)) return $gSavedBigBase2; 
     $BigBase=''; 
     for($i=ord('0');$i<=ord('1');$i++) $BigBase.=chr($i); 
     for($i=ord('A');$i<=ord('Z');$i++) $BigBase.=chr($i); 
     $BigBase.='_'; 
     // for($i=ord('a');$i<=ord('z');$i++) $BigBase.=chr($i); 
     $gSavedBigBase2=$BigBase; 
     return $BigBase; 
    } 

    function ConvertDecToAny($decstr,$decbase) { 
     $Result=array(); 

     do { 
      $Div=divide($decstr,$decbase); 
      $decstr=$Div[0]; 

      $Rest=$Div[1]; 
      $Result[]=$Rest; 

     } while($decstr!='0'); 

     return $Result; 
    } 

    function ConvertDecToAnyStr($decstr,$baseChars='01') { 

     $decbase=strlen($baseChars); 

     $Result=''; 

     do { 
      $Div=divide($decstr,$decbase); 
      $decstr=$Div[0]; 

      $Rest=$Div[1]; 
      $Result=$baseChars{$Rest}.$Result; 

     } while($decstr!='0'); 

     return $Result; 
    } 


    ?> 
Questions connexes