PHP函数式编程初探之“三板斧”:过滤、映射、归约
暗夜在火星 发表于7个月前
PHP函数式编程初探之“三板斧”:过滤、映射、归约
  • 发表于 7个月前
  • 阅读 52
  • 收藏 0
  • 点赞 0
  • 评论 0

IBM Bluemix免费试用!>>>   

函数式编程是一种不同于对象式编程的思想,虽然PHP并不是天生就属于函数式编程的语言,也不擅长该领域,但这里希望通过PHP对函数式支持实现,加深对函数式编程的范式和思想。

 

PHP本身的语法、语义不能完全很好地支持函数式编程,因为这里我需要通过实现封装类库来完成PHP对函数式编程的支持。

 

两个示例的最终效果

先来看下最终的效果:假设我们需要计算1到5之间的偶数之和的两倍,那么:

$fun = new Functional_Lite(range(1, 5));


$rs = $fun->filter(function ($x) { return $x % 2 == 0;})
            ->map(function ($x) {return $x * 2;})
            ->reduce(function ($x, $y) { return $x + $y;}, 0);

var_dump($rs); // 2 * 2 + 4 * 2 = 12

 

如果想更简短一点,可以这样使用字符串表达式:

$fun = new Functional_Lite(range(1, 5));


$rs = $fun->filter('$it % 2 == 0')
            ->map('$it * 2')
            ->reduce('$it_1 + $it_2', 0);

var_dump($rs); // 2 * 2 + 4 * 2 = 12

注意这里使用了 $it 来表示每次迭代的元素;对于reduce操作,使用了$it_1、$it_2分别表示第一个元素、第二个元素。

 

除了对数值进行操作,我们也希望可以对字符串或其他类型的集合进行操作,假设需要过滤一个字符的单词,然后把剩下的单词转大写,再用空格拼接起来。那么:

$fun = new Functional_Lite(array('dogstar', 'x', 'love', 'y', 'yoyo', '!!'));

$rs = $fun->filter(function ($x) { return strlen($x) > 1;})
            ->map(function ($x) { return strtoupper($x);})
            ->reduce(function ($x, $y) { return $x . ' ' . $y;}, 'RS:');

var_dump($rs); // RS: DOGSTAR LOVE YOYO !!

在上面,对于最后的结果,我们在累加量初始了“RS:”,所以最后的结果里有“RS:”的前缀。这里的一个问题是,还没想好如何更好地处理初始值。

 

同样,使用字符串表达式,可以简化上面的处理以达到同样的效果:

$rs = $fun->filter('strlen($it) > 1')
            ->map('strtoupper($it)')
            ->reduce('$it_1 . " " . $it_2', 'RS:');

 

至此,通过上面两个示例,可以看出都使用了函数式编程的“三板斧”:过滤、映射、归约。

对于这“三板斧”的定义和作用,这里不作过多的赘述。

 

类库实现

上面,我们封装了Functional_Lite这个类,以便更好的实现函数式编程。为了构造一个函数式的类库,可以传入一个集合,目前只支持数组,且会忽略索引。具体的源代码,可见GIT仓库:http://git.oschina.net/dogstar/functional_php

 

小结

当然,这里只是简单地实现了一下函数式编程最主要的三个操作:过滤、映射、归约。但离函数式编程的道路还很遥远,比如柯里化、部分施用、偏函数、Either类、Opeion类、值不可变。而且还有很多在PHP是明显很难实现的,如上下文的处理。

Anyway,这只是一个小开始,只是作为自己的一个小结。

 

共有 人打赏支持
暗夜在火星
粉丝 133
博文 135
码字总数 293508
作品 1
×
暗夜在火星
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: