电脑技术学习

PHP5.3闭包特性及应用详解

dn001

  09年7月发布的PHP 5.3 版本带来了很多新的特性,, 其中比较惹眼的特性之一就是支持了闭包;那么以后,我们也可以和那帮写 Ruby、Javascript 等等“高科技语言的家伙们一样,写出非常酷的代码吗?呃,其实大部分情况下是可以的,而有些方面还是令人非常的困扰,下面慢慢道来。

  很多语言的都提供了非常优雅和漂亮的操作数组的方法。在下面的例子中,会使用PHP5.3闭包特性以及其他语言提供的闭包功能,用于展示如何“客观的操作迭代数组。

  译注:原文作者比较火星,我不了解 Groovy 以及 Scala语言,所以这里我加上 Javascript 的实现。

  在开始之前先说明下,本例子仅仅是阐明观点,并没有考虑性能等其他方面的因素。
;

“货比三家

  用个简单的例子开始,有下面个数组:

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

需要找出数组中大于 15 的项。那么,不考虑闭包的情况下,我们或许会这样写:

  1. $res=;array(); ;
  2. foreach($numsas$n);{; ;
  3. if($n>;15);{$res[];=;$n ;
  4. } ;
  5. };

如果语言本身有闭包支持的,那么或许会这样写(Groovy 语言)

def res = nums.findAll { it > 15 }或者使用 Scala 语言

val res = nums filter (_ > 15)译注:Javascript 1.6 的话会是如下

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

因为循环操作已被抽象起来,所以可以看到 Groovy 、Scala (以及 Javascript) 都很漂亮得用一行就可以搞定。

当然,如果使用 PHP5.3 的闭包,也可以做到

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

PHP 在这方面使用了比 Scala 更多的字符,但对比先前的例子,它更简短并且能更好得阅读。

顺便说下,上面的 PHP 代码实际上是使用了 Lambda 解析式,并不是个真正的闭包,这个 并不是我们目前关注的重点。详细阐述 PHP 闭包以及 Lambda 解析式的资料,可以参考这里。

目前看来感觉都还不错,那么我们再的题目增加点难度:找到所有大于 15 的项, 然后乘以 2 再加上作用域中的的某个变量值以后再返回。

Groovy 的实现:

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

Scala 的实现:

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

PHP的实现:

  1. $x=;1; ;
  2. $res=;array_map( ;
  3. function($v);use($x);{; ;
  4. return$v*;2;+;$x},;;;
  5. array_filter($nums, ;
  6. function($v);{;return$v>;15;;}) ;
  7. ); ;

光从代码量方面,现在看起来 PHP 与其他语言有出入了。先抛开代码字面上本身 的审美不谈,上面的 PHP 代码还有个额外的问题。

例如,如果需要使用数组的键而非值作比较,怎么办?是的,上面的代码就办不到了。同时,从语法角度上说,上面的代码非常难以阅读。

返璞归真,这时还是得返回老土的思路去解决问题:

  1. $x=;1; ;
  2. $res=;array(); ;
  3. foreach($numsas$n);{ ;
  4. if($n>;15);{ ;
  5. $res[];=;$n*;2;+;$x ;
  6. } ;
  7. };

这样看起来又很清楚了。但这个时候你或许又会迷惑了:“那还瞎折腾啥,这不就是个数组操作吗?。

是的,好戏还在后头。这个时候该让 PHP 的某些高级特性出场,来搞定这看似有自残倾向 的“无聊问题。

标签: