Анонимные функции (лямбды, замыкания) в PHP 4

Есть ли хитрость в PHP 4 для реализации функций, которые возвращают функции? Я ожидал, что следующий код будет работать:

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

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

К сожалению, не повезло в PHP 4. Вероятно, это работает в PHP 5, но я ограничился PHP 4.

Я попытался обойти OO, но снова не удалось (объявления классов не могут быть вложенными):

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);

Есть функция "create_function", но она очень ограничена: тело должно быть строкой.

Есть другие идеи?

2 ответа

Решение

Вы, вероятно, лаете не на то дерево. PHP не является функциональным языком программирования. Некоторые изменения были внесены, начиная с PHP 5.3, но даже там у вас нет ожидаемых областей видимости переменных, которые позволили бы вам делать то, что вы имеете в своих примерах.

Единственные инструменты, которые вы можете использовать в PHP 4, это create_function и некоторая изобретательность, чтобы написать определение функции в виде строки.

<?php

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

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

?>

... но даже если это просто для вашего опубликованного примера, это определенно не практично для более сложных ситуаций.

В PHP4 вы можете использовать переменные функции, как это, при условии, что ваша функция уже определена в области видимости (поэтому не является настоящим замыканием).

Это грязный код. ЭТО НЕ МНОГО ПРОВЕРЕНО. ЭТО НЕ БЫСТРО (даже медленнее, чем замыкания, если это возможно). Это просто для удовольствия, и доказать это "как-то" можно, если вам действительно это нужно.

Требуется доступный для записи каталог tmp/.

    <?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;
    }


    ?>
Другие вопросы по тегам