anonymous functions (lambdas, closures) in PHP 4

2019-02-26 04:36发布

Is there a trick in PHP 4 to implement functions which return functions? I expected that the following code would work:

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

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

Unfortunately, no luck in PHP 4. Probably it works in PHP 5, but I limited to PHP 4.

I tried to workaround with OO, but again failed (class declarations may not be nested):

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

There is a function "create_function", but it is very limited: the body must be a string.

Any other ideas?

标签: php php4
2条回答
Explosion°爆炸
2楼-- · 2019-02-26 05:02

In PHP4 you can use Variable Functions like this, provided your function is already defined in the scope (so not a real closure).

THIS IS DIRTY CODE. THIS IS NOT MUCH TESTED. THIS IS NOT FAST (even slower than closures if that is possible). It is just for fun and proving it "somehow" can be done if you really really need it.

Requires a writable tmp/ directory.

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


    ?>
查看更多
相关推荐>>
3楼-- · 2019-02-26 05:04

You're probably barking at the wrong tree. PHP is not a functional programming language. Some changes have been made starting with PHP 5.3, but even there you don't have your expected variable scopes that would allow you to do what you have in your examples.

The only tools you can use in PHP 4 are create_function and some ingenuity to write the function definition as a string.

<?php

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

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

?>

...but even if this is simple for your posted example, it definitely isn't practical for more complex situations.

查看更多
登录 后发表回答