PHP closure problems in practical application

Source: Internet
Author: User
Tags php oop

The new version of PHP5.3 follows many new features. One of the most eye-catching features is the support for closures. In the future, can we write cool code like those who write Ruby, Javascript, and other "high-tech languages? Er, in most cases, it is possible, but some aspects are still very troublesome. Let's take a look at it.

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 is used to demonstrate how to "objectively" operate iterative arrays.

The author of the original article compares Mars. I don't know Groovy and Scala, so here I add Javascript implementation.

Before you start, Let's explain that this example only clarifies your point of view and does not consider performance and other factors.

"Goods Comparison Three"

Starting with a simple example, we have the following array:

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

You need to find more than 15 items in the array. If we do not consider the closure, we may write as follows:

$res = array();
foreach ($nums as $n) {
if ($n > 15) {
$res[] = $n;
}
}

If the language itself supports closures, it may be written like this (Groovy language)

def res = nums.findAll { it > 15 }

Or use the Scala language.

val res = nums filter (_ > 15)

Note: Javascript 1.6 is as follows:

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

Because loop operations have been abstracted, we can see that Groovy, Scala (and Javascript) are pretty good and can be done with a line.

Of course, if you use the closure of PHP5.3, you can also

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

PHP uses more characters than Scala in this regard, but it is shorter and easier to read than the previous example.

By the way, the above PHP Code actually uses the Lambda analytical expression, not a real closure, which is not the focus of our current attention. For details about the PHP closure and Lambda analysis, refer to here.

At present, it seems that it is not bad, so we will make it more difficult to solve the problem: Find all the items greater than 15, multiply by 2 and add a variable value in the scope, and then return.

Groovy implementation:

def x = 1
def res = nums .findAll { it > 15 } .collect { it * 2 + x }

Scala implementation:

val x = 1
val res = nums filter (_ > 15) map (_ * 2 + x)

Implementation of annotation and Javascript:

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

And PHP:

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

In terms of the amount of code, it seems that PHP is different from other languages. Aside from the literal aesthetic of the Code, the above PHP code has an additional problem.

For example, what if we need to use the array key instead of the value for comparison? Yes, the above Code cannot be done. At the same time, from the syntax point of view, the above code is very difficult to read.

Back to the original, you still have to return to the old ideas to solve the problem:

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

So it looks clear again. But at this time, you may be confused: "What is it? Isn't it an array operation ?".

Yes, it's still the beginning. At this time, some advanced features of PHP should be introduced to solve this seemingly self-defeating "boring problem ".

ArrayObject-encapsulation of Arrays

PHP has a standard library called SPL, which contains a class called ArrayObject. It can provide the "like an array operation class" function, for example

$res = new ArrayObject(array(10, 20, 30, 40));
foreach ($res as $v) {
echo "$vn";
}

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

Arr-sugar coated

Now that we have the features of ArrayObject and closure, we can try to encapsulate it:

class Arr extends ArrayObject
{
static function make($array)
{
return new self($array);
}

function map($func)
{
$res = new self();
foreach ($this as $k => $v) {
$res[$k] = $func($k, $v);
}
return $res;
}

function filter($func)
{
$res = new self();
foreach ($this as $k => $v) {
if ($func($k, $v)) {
$res[$k] = $v;
}
}
return $res;
}
}

All right, everything is ready. The PHP code rewritten below can solve the problem mentioned above, and it seems that the syntax is "not much:

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

What is the difference between the above Code and the traditional method? First, they can be recursive and form a function chain call, so more similar operations can be added.

At the same time, you can use the two callback parameters to operate the keys of the array and the keys corresponding to the-$ k key and the corresponding values of $ v. This allows us to use the key value in the closure, which cannot be implemented in the traditional PHP function array_fliter.

The additional benefit is more consistent API calls. Using traditional PHP functions, they may be a closure, an array, or multiple arrays... Who knows?

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

Game

This is actually hard to answer-it depends on the context of the Code and the programmer's own and many other factors. In fact, when I first saw the PHP closure implementation, I felt like I was back to the Java period a long time ago. At that time, I began to use the anonymous built-in class (anonymous inner classes) to implement the closure. Of course, although this can be done, it seems to be a little superfluous. PHP closure itself is correct, but its implementation and syntax make me very confused.

Other languages with the closure feature can conveniently call the closure and have elegant syntax at the same time. In the above example, the traditional loop can also work in Scala, but will you write it like this? On the other hand, some people say that the above question can also be implemented using the closure of PHP, but will you write it like this in general?

It can be determined that the PHP closure can become a sharp military knife (such as delayed execution and resource calling) in some cases, but it is difficult for traditional iterations and Array Operations. Don't be discouraged. Writing compatible and refreshing code and APIS is the most important thing.

Conclusion

Just like all the syntax features added later (Do you remember the Java Generics feature? And the php oop features of the past few years), they all need time to work together and ultimately stabilize. As PHP5.3 and PHP6 become more popular in the future, more and more skills and features are believed to be gradually mined by smart programmers in the near future.

Return to the question at the beginning of the first article, and compare

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

And

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

The difference between the two. In the final analysis, they are just syntaxes. In essence, they all solve the same problem. If the application features of programming languages are different, the advantages and disadvantages of programming languages cannot be compared.

Finally, here is an example of the Code in this article. I believe we can find more ideas on how to use PHP for functional iteration (not just that of course.

Link: http://justafewlines.com/2009/10/whats-wrong-with-php-closures/

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.