是否可以在PHP5.2.x中不使用全局变量来模拟闭包?

是否可以在PHP5.2.x中不使用全局变量来模拟闭包?,php,closures,global-variables,simulate,Php,Closures,Global Variables,Simulate,是否可以在PHP5.2.x中不使用全局变量来模拟闭包?我可以想出一种方法,将所需的变量作为额外参数传递给闭包,但这并不是最佳实践 有什么想法吗?你是说像咖喱一样的东西吗 然后 如果没有,没关系。:-) 有趣的问题。我想说这根本不可能,但让我们看看 引用 闭包是在自己的环境中进行计算的函数,它有一个或多个绑定变量,在调用该函数时可以访问这些变量 还有(我的重点) 要从外部环境导入的变量在闭包函数定义的use子句中指定。默认情况下,它们通过值传递,这意味着如果我们更新闭包函数定义中传递的值,它将不会

是否可以在PHP5.2.x中不使用全局变量来模拟闭包?我可以想出一种方法,将所需的变量作为额外参数传递给闭包,但这并不是最佳实践


有什么想法吗?

你是说像咖喱一样的东西吗

然后


如果没有,没关系。:-)

有趣的问题。我想说这根本不可能,但让我们看看

引用

闭包是在自己的环境中进行计算的函数,它有一个或多个绑定变量,在调用该函数时可以访问这些变量

还有(我的重点)

要从外部环境导入的变量在闭包函数定义的use子句中指定。默认情况下,它们通过值传递,这意味着如果我们更新闭包函数定义中传递的值,它将不会更新外部值

使用
global
将通过引用传递,尽管在
use
子句中使用
&
可以通过引用与闭包绑定变量,但这已经偏离了5.3默认行为

$var = 'yes';
$fn  = create_function('', 'global $var; $var = "no";');
$fn();
echo $var; // outputs no
您可以复制全局变量,以便按值使用它,例如

$var = 'yes';
$fn  = create_function('', 'global $var; $tmp = $var; $tmp = "no";');
$fn();
echo $var; // outputs yes
此外,全局变量的值(使用
create_function
时)在创建函数时不会计算(绑定),而是在运行函数时计算(绑定)

$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
同样重要的是

当在对象中定义时,一件方便的事情是闭包可以通过$this变量完全访问对象,而无需显式导入它*虽然我认为这是在最后的PHP5.3中删除的

使用
global
关键字是不可能的,您也不能只使用
$This
。使用
create\u 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();
将导致

Fatal error: Using $this when not in object context
总之
虽然可以创建从全局范围导入变量的函数,但不能使用其他范围的变量创建函数。由于在使用
create\u函数时,您在技术上没有绑定,而是在执行创建的函数时导入,因此我想指出此限制使闭包成为lambda


编辑:下面由Onno Marsman提供的解决方案是相当不错的。它没有完全模拟闭包,但实现非常接近。

我的解决方案:


但是,它确实会将对象中的变量作为第一个参数传递给闭包。

在某些特殊情况下,您可以这样做

如果需要通过值(而不是引用)捕获变量,并且值是简单的值类型,如数字、字符串或上述数组(而不是引用类型,如对象、资源和函数),则可以使用
var\u export()
将其插入函数定义中:

如果需要通过引用捕获变量,以便在函数调用中保持可变状态,但不需要在创建变量的原始范围中反映更改(例如,创建累加器,但对总和的更改不需要在创建范围中更改总和变量),然后可以类似地插入它,但作为静态变量:

function make_accumulator($sum) {
    $f = create_function('$x',
        'static $var=' . var_export($var,true) . '; return $var += $x;');
    return $f;
}

很遗憾,PHP不支持这样一个很棒的构造。@Chaospandio,但它是从PHP5.3 upwell开始的,是的,但您必须显式地列出封闭变量。可以说是“拄着拐杖关门”。但总比什么都没有好。没有语言来形容这有多可怕。(不是你的答案。)回答得好!全局变量绑定的细节让我在PHP5.2.17上维护一个遗留项目,从而避免了很多麻烦。荣誉这并不完全是我的意思,但还是有一个很好的链接:虽然在技术上不得不调用call(),但在我看来,这并不能算是一个结束(至少在某种程度上)。此外,我还发现必须传入闭包实例才能获得闭包变量有点尴尬,并且调用_user_func_数组应该返回。但还是很好。您是在5.3中的闭包类之后建模的吗?在意识到PHP5.3中甚至存在一个内部闭包类之前,我首先想到了这个解决方案。我自己不喜欢调用call(),只会使用u invoke magic方法,除非它在PHP5.3之前不可用……戈登:“call_user_func_数组应该返回”是什么意思?
function make_accumulator($sum) {
    $f = create_function('$x',
        'static $var=' . var_export($var,true) . '; return $var += $x;');
    return $f;
}