这篇文章翻译了Anonymous Functions VS Closures
是不是很想知道匿名函数和闭包之间的关系?Lambda呢?这些在PHP中是如何实现的呢?在这个领域有很多困惑,现在让我们来深挖并回答这些问题。
第一件事:Lambda
是匿名函数的别称。在一些编程语言(如python)中使用Lambda。
接下来让我们看看匿名函数和闭包到底是什么。如果现在你很困惑,不用担心,接下来我希望能够让你明白,下面是两者的一个简单定义:
- 匿名函数:一个匿名函数是一个定义的偶尔触发的函数,不需要与标识符绑定。(An Anonymous Function is a function that is defined, and occasionally invoked, without being bound to an identifier. It also has the variable scoping characteristics of a Closure (see below))。
- 闭包函数:闭包是一个能够捕获当前包含作用域,能够获取父作用域的函数。闭包将非局部变量的引用绑定到了闭包创建时的作用域。(A Closure is a function that captures the current containing scope, then provides access to that scope when the Closure is invoked. The Closure binds non-local variable references to the corresponding variables in scope at the time the Closure is created.)
从这儿可以看到:所有的匿名函数都是闭包,但并不是所有的闭包都是匿名函数。
用外行的话来说:
所有的匿名函数都是没有名字的闭包。闭包是一个函数,在闭包定义的时候会将非局部变量绑定为函数的局部变量。(原文:An Anonymous Function is a Closure without a name. A Closure is a function which binds references to non-local variables to local variables inside the function at the time of the Closure definition.)
关于PHP呢?
事情变得有趣了。在PHP5.3中加入了匿名函数和闭包。但是,有一些取巧的地方(其中一个已经在PHP5.4中修复)
匿名函数的实现是Closure对象。PHP贯彻了观点匿名函数是一个无名的闭包
。
有一个简单的匿名函数传递给array_map
函数,目的是将所有的整数都乘以2。
$arr = array_map(function ($val) {
return is_int($val) ? $val * 2 : $val;
}, $arr);
很简答,对不?现在问一下自己:如果你想在函数内部访问非局部变量(non-local variables)?毕竟匿名函数也是闭包。当然可以,但是你必须清晰告诉PHP使用哪些非局部变量,这是诸多取巧的第一个。现在开始深挖。
####取巧1:
当使用非局部变量时,必须使用关键字use
将这些非局部变量绑定到闭包的作用域。这与大部分其他语言都不一样。
$foo = 'foo';
$bar = 'bar';
$baz = function () use ($foo, $bar) {
echo $foo, $bar;
};
【译者备注】这儿绑定到闭包的作用域,是将这些非局部变量作为了闭包的静态变量
####取巧2:
绑定的非局部变量是复制,而不是引用。如果你想在闭包中改变变量的值,那么你必须使用引用传递。
$foo = 'foo';
$bar = 'bar';
$baz = function () use (&$foo, &$bar) {
$foo = 'Hello ';
$bar = 'World!';
};
$baz();
echo $foo, $bar; // Outputs "Hello World!";
####取巧3:
在PHP5.3中,在类中使用闭包,闭包不能使用$this
。你必须传递this的引用,而不能直接传递$this
。
在PHP5.4中修复,可以直接传递$this
。