PHP 4中的匿名函数(lambdas,closures)

时间:2010-11-11 14:15:51

标签: php php4

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 个答案:

答案 0 :(得分:4)

你可能在错误的树上吠叫。 PHP不是函数式编程语言。有些changes是从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);

?>

...但即使这对于您发布的示例来说很简单,对于更复杂的情况来说也绝对不实用。

答案 1 :(得分:0)

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


    ?>