douli8428 2010-02-05 18:12
浏览 48
已采纳

是否可以在PHP 5.2.x中模拟闭包而不使用全局变量?

Is it possible to simulate closures in PHP 5.2.x not using globals? I could think of a way that would pass the desired variables as extra parameters to the closure but that just doesn't feel like best practice.

Any ideas?

  • 写回答

4条回答 默认 最新

  • doukong9316 2010-02-05 18:54
    关注

    Interesting question. I'd say it's not possible at all, but let's see

    Quoting IBM - What's new in PHP5.3, Part 2

    A closure is a function that is evaluated in its own environment, which has one or more bound variables that can be accessed when the function is called.

    and further (emphasis mine)

    Variables to be imported from the outside environment are specified in the use clause of the closure function definition. By default, they are passed by value, meaning that if we would update the value passed within the closure function definition, it would not update the outside value.

    Using global would pass by reference and although it is possible to bind variables by reference with a closure by using & in the use clause, it is already a deviation from the 5.3 default behavior.

    $var = 'yes';
    $fn  = create_function('', 'global $var; $var = "no";');
    $fn();
    echo $var; // outputs no
    

    You could copy the global variable in order to use it by value though, e.g.

    $var = 'yes';
    $fn  = create_function('', 'global $var; $tmp = $var; $tmp = "no";');
    $fn();
    echo $var; // outputs yes
    

    In addition, the value of the global variable (when using create_function) will not be evaluated (bound) when the function is created but when the function is run

    $var = 'yes';
    $fn  = create_function('', 'global $var; $tmp = $var; return $tmp;');
    $var = 'maybe';
    echo $fn(); // outputs maybe
    
    $var = 'yes';
    $fn  = function() use ($var) { return $var; };
    $var = 'maybe';
    echo $fn(); // outputs yes
    

    Also important is

    When defined within an object, one handy thing is that the closure has full access to the object through the $this variable, without the need to import it explicitly. *Though I think this was dropped in final PHP5.3

    This is impossible with the global keyword and you also cannot just use $this. There is no way to reference a property from a class when defining the function body with create_function.

    class A {
    
        protected $prop = 'it works';
    
        public function test()
        {
            $fn = create_function('', 'echo $this->prop;');
            return $fn;
        }
    }
    
    $a = new A;
    $fn = $a->test();
    $fn();
    

    will result in

    Fatal error: Using $this when not in object context
    

    To sum this up
    While you can create a function importing a variable from the global scope, you cannot cannot create one using variables from another scope. And because you are technically not binding when using create_function but importing when the created function is executed, I'd like to argue this limitation makes the closure a lambda.


    EDIT: The solution offered by Onno Marsman below is pretty decent though. It doesn't fully simulate Closures, but the implementation is pretty close.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题