Talking about the problems of PHP closure feature in practical application_PHP Tutorial

WBOY
Release: 2016-07-13 17:38:41
Original
784 people have browsed it

The new version of PHP5.3 follows many new features, one of the more eye-catching features is the support for closures. So in the future, can we write very cool code like those guys who write Ruby, Javascript and other "high-tech languages"? Well, in fact, it is possible in most cases, but some aspects are still very troubling. Let’s talk about it slowly.

Many languages ​​provide very elegant and beautiful methods for operating arrays. In the following example, the closure function provided by PHP5.3 and other languages ​​will be used to show how to "objectively" operate the iterated array.

Translation Note: The author of the original article is relatively incompetent. I don’t know Groovy and Scala language, so I will add the Javascript implementation here.

Before I start, let me explain that this example is just to illustrate the point and does not take into account other factors such as performance.

“Shop around”

Let’s start with a simple example. There is the following array:

$nums = array(10, 20, 30, 40);
Copy after login

Need to find items greater than 15 in the array. Then, without considering closure, we might write like this:

$res = array();<br>foreach ($nums as $n) {<br>    if ($n > 15) {<br>        $res[] = $n;<br>    }<br>}
Copy after login

If the language itself has closure support, then it might be written like this (Groovy language)

def res = nums.findAll { it > 15 }
Copy after login

Or use Scala language

val res = nums filter (_ > 15)
Copy after login

Annotation: Javascript 1.6 would be as follows

var res = nums.filter(function(c){return c > 15});
Copy after login

Because the loop operation has been abstracted, you can see that Groovy, Scala (and Javascript) are all beautiful and can be done in one line.

Of course, if you use PHP5.3 closures, you can also do it

$res = array_filter($nums, function($v) { return $v > 15; });
Copy after login

PHP uses more characters than Scala for this, but compared to the previous example, it's shorter and easier to read.

By the way, the above PHP code actually uses Lambda analysis and is not a real closure. This is not the focus of our current attention. For detailed information on PHP closures and Lambda parsing, please refer here.

So far it seems to be pretty good, so let’s increase the difficulty of the problem: find all items greater than 15, then multiply by 2 plus a certain variable value in the scope and then return.

Groovy implementation:

def x = 1<br>def res = nums .findAll { it > 15 } .collect { it * 2 + x }
Copy after login

Scala implementation:

val x = 1<br>val res = nums filter (_ > 15) map (_ * 2 + x)
Copy after login

Translation annotation, Javascript implementation:

var i = 1;<br>var res = nums.filter(function(c){return c > 15}).map(function(c){return c * 2 + i});
Copy after login

and PHP:

$x = 1;<br>$res = array_map(<br>    function($v) use ($x) { return $v * 2 + $x; },<br>    array_filter(<br>        $nums,<br>        function($v) { return $v > 15; })<br>);
Copy after login

In terms of code size, it seems that PHP is different from other languages. Leaving aside the literal aesthetics of the code, there is an additional problem with the PHP code above.

For example, what if you need to use array keys instead of values ​​for comparison? Yes, the above code cannot be done. Also, syntactically speaking, the above code is very difficult to read.

Back to nature, you still have to go back to the old-fashioned way of thinking to solve the problem:

$x = 1;<br>$res = array();<br>foreach ($nums as $n) {<br>    if ($n > 15) {<br>        $res[] = $n * 2 + $x;<br>    }<br>}
Copy after login

Phew, this looks clear again. But at this time, you may be confused again: "Why bother messing around? Isn't this just an array operation?".

Yes, the best is yet to come. At this time, it is time to let some advanced features of PHP come into play to solve this "boring problem" that seems to have a tendency to self-harm.

ArrayObject – a wrapper for arrays

PHP has a standard library called SPL, which contains a class called ArrayObject, which provides the function of "operating classes like arrays", such as

$res = new ArrayObject(array(10, 20, 30, 40));<br>foreach ($res as $v) {<br>    echo "$vn";<br>}
Copy after login

ArrayObject is a built-in class, so you can encapsulate it like other class operations.

Arr - sugar coated

Now that we have ArrayObject and closure features, we can start trying to encapsulate it:

class Arr extends ArrayObject<br>{<br>    static function make($array)<br>    {<br>        return new self($array);<br>    }<br><br>    function map($func)<br>    {<br>        $res = new self();<br>        foreach ($this as $k => $v) {<br>            $res[$k] = $func($k, $v);<br>        }<br>        return $res;<br>    }<br><br>    function filter($func)<br>    {<br>        $res = new self();<br>        foreach ($this as $k => $v) {<br>            if ($func($k, $v)) {<br>                $res[$k] = $v;<br>            }<br>        }<br>        return $res;<br>    }<br>}
Copy after login

Okay, everything is ready. The rewritten PHP code below can solve the problems mentioned above, and looks "almost" syntactically:

$res = Arr::make($nums)<br>    ->filter(function($k, $v) { return $v > 15; })<br>    ->map(function($k, $v) { return $v * 2; });
Copy after login
Copy after login

How is the above code different from the traditional method? First, they can be recursive and chain calls, so more similar operations can be added.

At the same time, the keys and values ​​of the array can be manipulated respectively through the two parameters of the callback - $k corresponds to the key and $v corresponds to the value. This allows us to use key values ​​in closures, which is not possible with the traditional PHP function array_filter.

Another added benefit is more consistent API calls. Using traditional PHP function operations, their first parameter may be a closure, or an array, or multiple arrays... Anyway, who knows?

Here is the complete source code of the Arr class, which also contains other useful functions (similar to reduce and walk). In fact, their implementation is similar to the code.

Game

This question is actually difficult to answer - it depends on many factors such as the context of the code and the programmer himself. In fact, when I first saw PHP's closure implementation, I felt like I was back in the Java days long ago, when I started using anonymous inner classes to implement closures. Of course, this can be done, but it seems superfluous. There is nothing wrong with PHP closures, but its implementation and syntax confuse me.

其他具有闭包特性的语言,它们可以非常方便的调用闭包并同时具有优雅的语法。在上面的例子 中,在 Scala 中使用传统的循环也可以工作,但你会这样写吗?而从另个方面,那么有人 说上面这个题目使用 PHP 的闭包也可以实现,但一般情况下你会这样写吗?

可以确定,PHP 闭包在些情况下可以成为锐利的军刀(例如延时执行以及资源调用方面), 但在传统的迭代以及数组操作面前就显得有些为难。不要气馁不管怎么样, 返璞归真编写具有兼容性的、清爽的代码以及 API 是最重要的。

结束语

像所有后来加上的语法特性一样(记得当年 Java 的 Generics 特性不?以及前几年的 PHP OOP 特性),它们都需要时间磨合以及最终稳定下来。随着 PHP5.3 甚至将来的 PHP6 逐渐普及,越来越多的技巧和特性相信在不远的将来逐渐的被聪明的程序员挖掘出来。

回到最初文章开头那个题目,对比

$res = Arr::make($nums)<br>    ->filter(function($k, $v) { return $v > 15; })<br>    ->map(function($k, $v) { return $v * 2; });
Copy after login
Copy after login

以及

val res = nums filter (_ > 15) map (_ * 2)
Copy after login

两者之间的区别。归根结底它们仅是语法而已,本质上都是殊途同归解决了同个问题。程序 语言的应用特性不同,自然孰优孰劣也就无从比较。

最后,这里有此篇文章的代码示例, 相信可以找到更多如何使用 PHP 进行函数式迭代(当然不仅仅是这些)的心得。

-- Split --

不靠谱之博主心得

坦白讲,虽然在 PHP5.0 之前就了解过提出的新增闭包等功能,但在看到 PHP5.3 提供的闭 包以及 Lambda 功能后,与原本心理期待的还是有些出入。

甚至相对于熟悉的 JavaScript,PHP 的闭包在我看来,像是“别的语言都有了,所以我也要有” 的这种心态下的产物。

但正如上文中所言,相比 JavaScript 等其他动态语言,PHP 出于自身的应用以及实现的哲学 出发,与其他开发语言不尽相同。

因此在某些特性的调用方式、实现方法也会不一样,这难免会让熟悉另外具有类似功能的语言 的人感到的不适应。

从 PHP5.3 推出至今,还不到半年的时间,相比 JavaScript 等这些早已具有闭包等特性的 动态语言相比,自然是显得非常稚嫩。

同时,广大的开发者对于 PHP5.3 提供的包括闭包在内的新特性还在持观望态度。PHP 的闭包特性目前还是存在于实验室中,其应用于实际开发如要突破的不仅仅是语言特性 ,还要经过效率、安全性等方面的考验。

但相信,如原文作者所言,随着 PHP 版本的推进,PHP 的闭包应用场合会越来越频繁。像 当年 PHP4 转换到 PHP5 一样,对语言新特性的适应,其实是种痛并快乐着的过程。

文章来源: www.2cto.com

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/486467.htmlTechArticlePHP5.3 新版本跟随了很多新特性, 其中比较惹眼的特性之一就是支持了闭包。那么以后,我们也可以和那帮写 Ruby、Javascript 等等高科技语言...
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!