php闭包:下一步该怎么做


php Closure: what to do next with it?

我有一些简单的例子:

function func1(){
    return function (){
        return 1;
    };
}

但我还不清楚我该如何利用它。看起来func1()的返回与匿名函数的返回完全相同。但如果我这样写:

echo func1();

我得到一个错误:

Catchable fatal error: Object of class Closure could not be converted to string in [file_name] on line [line]

我只能得到一个闭包对象:

var_dump(func1());
---------------------
object(Closure)[1]

然而,我看不出这有什么实际用途。无论匿名函数返回什么,它总是包含相同的对象-object(Closure)[1]。(我使用php 5.3.3)此外,我认为没有办法存储匿名函数在func1()中返回的值。在我看来,无论如何,它都是一个封闭的对象。但是如何在那里和其他地方使用它呢?

在您的示例中,对func1的调用的返回值是一个函数(更具体地说,是一个Closure)。您得到的错误是由于php无法将此对象转换为字符串。如果你想打印闭包返回的值,你需要调用它。

function func1() {
    return function () {
        return 1;
    };
}
$f = func1(); // Create the closure
echo $f();    // Calls the closure

这个例子只是一个返回函数的函数,并没有说明是什么将闭包与任何其他第一类函数区分开来,也就是说,闭包可以包含其创建所特有的状态。换句话说,您可以从相同的代码中生成函数,这些代码可以访问的数据不同。

考虑一下这个琐碎的例子:

 function multiplier($m) {
     return function ($v) use ($m) {
         return $v * $m;
     };
 }
 $mult_5 = multiplier(5);
 echo $mult_5(5); // prints 25
 $mult_10 = multiplier(10);
 echo $mult_10(5); // prints 50

同样,这是一个非常琐碎的例子,但它确实展示了一些重要的东西。首先,我们只定义了一个函数,但通过调用这个函数,我们只需在调用时更改参数,就可以生成两个相似但不同的函数。此外,考虑每个函数都有自己的"状态"。在我命名为$mult_5的函数的情况下,它知道它自己的内部$m值是5,这与$mult_10函数的$m值不同。其中每一个的值都被传递给multiplier函数,该函数已经完成,但该值仍然存在于返回的函数/闭包中。

还值得注意的是,调用multiplier的每个返回值都是一个第一类函数,这意味着您可以编写通用函数(如multiplier),然后使用它们"动态"生成更具体的函数,这些函数更适合程序的当前环境/状态。

如果你熟悉OOP,上面的例子可以很容易地使用OOP:重写

class Multiplier {
        protected $m;
        public function __construct($m) {
                $this->m = $m;
        }
        public function multiply($v) {
                return $v * $this->m;
        }
}
$mult_5 = new Multiplier(5);
echo $mult_5->multiply(5);  // prints 25
$mult_10 = new Multiplier(10);
echo $mult_10->multiply(5); // prints 50

而且,这是非常主观的,但我更喜欢闭包的更一致的语法。

或者,您可以使用一个更通用的函数来开始:

function multiplier($a, $b) {
    return $a * $b;
}
echo multiplier(5, 5);
echo multiplier(5, 10);

但是使用闭包的好处是可以隐藏数据(如本例中的乘数)。

当您将匿名函数用作array_filter()等函数的参数时,它们会变得非常有用。请参阅此处的文档。

此外,已经尝试过这样做:

$x = func1();
echo $x();

如果是这样,结果将取决于如何定义func1