文档章节

PHP函数式编程初探之“三板斧”:过滤、映射、归约

暗夜在火星
 暗夜在火星
发布于 2016/11/20 15:59
字数 754
阅读 92
收藏 0
点赞 0
评论 0

函数式编程是一种不同于对象式编程的思想,虽然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,这只是一个小开始,只是作为自己的一个小结。

 

© 著作权归作者所有

共有 人打赏支持
暗夜在火星

暗夜在火星

粉丝 150
博文 160
码字总数 310930
作品 1
广州
程序员
向你老婆解释清楚MapReduce

文章转载自「开发者圆桌」一个关于开发者入门、进阶、踩坑的微信公众号 干巴巴的定义 MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算。概念"Map(映射)"和"Reduce(归约)...

开发者圆桌
2017/03/30
0
0
【编译原理】中间代码(二)

本文是关于中间代码的第二篇文章。在第一篇文章中,我们介绍了3种表示中间代码的方式,本文将接着介绍和静态类型检查以及中间代码生成相关的内容。另外,本文使用第一篇文章中介绍的三地址代...

jzyhywxz
2017/12/13
0
0
inspired by Lisp/Scheme

“不区分数据与操作”这句话说起来很简单,其实背后蕴含着一个重要的哲学问题,即“什么是时间”的问题。按照过程式编程的理念,“时间”是操作内部的一个变量,程序以局部变量的形式记录系统...

AdamWu
2012/06/16
0
0
函数式编程初探

诞生50多年之后,函数式编程(functional programming)开始获得越来越多的关注。 不仅最古老的函数式语言Lisp重获青春,而且新的函数式语言层出不穷,比如Erlang、clojure、Scala、F#等等。...

阮一峰
2012/04/06
0
0
函数式编程初探

诞生 50 多年之后,函数式编程(functional programming)开始获得越来越多的关注。 不仅最古老的函数式语言 Lisp 重获青春,而且新的函数式语言层出不穷,比如 Erlang、clojure、Scala,、F...

墙头草
2012/04/06
4.5K
24
Scala之集合上常见的函数式风格的操作汇总

目录 正文 函数式编程对集合操作有一些通行的“叫法”,或者更像是一些“俚语”,它们的含义清晰明确,但是很难顾名思义,比如常见的“filter”,”map”,”flatMap”,“redue”等等。本文会...

bluishglc
2016/11/24
0
0
你真的理解【函数式编程】吗?

本文来自作者 李龙生 在 GitChat 上分享「你真的理解函数式编程吗?」,「阅读原文」查看交流实录 「文末高能」 编辑 | 克拉克 前言 现在机器学习、人工智能的发展趋势如火如萘,很多培训班也...

gitchat
2017/11/28
0
0
通俗解释什么是响应式编程

响应式编程(Reactive Programming 或称反应式编程)是一种流行的编程方法,编写代码是基于对变化的反应。它的灵感来自于我们的日常生活,也即我们如何采取行动以及与他人沟通。 我们在执行日常...

angeChen
2017/12/14
0
0
利用php数组函数进行函数式编程

因为一个BUG, 我在一个摇摇欲坠,几乎碰一下就会散架的项目中某一个角落中发现下面这样一段代码 这段程序与那个BUG有密切的关系。 我来回反复的捉摸这段代码, 发现这段代码实现了两个功能 ...

科技探索者
2017/11/10
0
0
Hadoop简要介绍

本文大部分内容都是从官网Hadoop上来的。其中有一篇介绍HDFS的pdf文档,里面对Hadoop介绍的比较全面了。我的这一个系列的Hadoop学习笔记也是从这里一步一步进行下来的,同时又参考了网上的很...

晨曦之光
2012/03/09
168
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

代码生成利器:IDEA 强大的 Live Templates

代码生成利器:IDEA 强大的 Live Templates

qwfys
16分钟前
1
0
spring boot使用通用mapper(tk.mapper) ,id自增和回显等问题

最近项目使用到tk.mapper设置id自增,数据库是mysql。在使用通用mapper主键生成过程中有一些问题,在总结一下。 1、UUID生成方式-字符串主键 在主键上增加注解 @Id @GeneratedValue...

北岩
19分钟前
0
0
告警系统邮件引擎、运行告警系统

告警系统邮件引擎 cd mail vim mail.py #!/usr/bin/env python#-*- coding: UTF-8 -*-import os,sysreload(sys)sys.setdefaultencoding('utf8')import getoptimport smtplibfr......

Zhouliang6
22分钟前
0
0
日常运维--rsync同步工具

rsync命令是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件。rsync使用所谓的“rsync算法”来使本地和远程两个主机之间的文件达到同步,这个算法只传送两个文件的不同部分,而...

chencheng-linux
26分钟前
1
0
Java工具类—随机数

Java中常用的生成随机数有Math.random()方法及java.util.Random类.但他们生成的随机数都是伪随机的. Math.radom()方法 在jdk1.8的Math类中可以看到,Math.random()方法实际上就是调用Random类...

PrivateO2
38分钟前
1
0
关于java内存模型、并发编程的好文

Java并发编程:volatile关键字解析    volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果。在...

DannyCoder
昨天
0
0
dubbo @Reference retries 重试次数 一个坑

在代码一中设置 成retries=0,也就是调用超时不用重试,结果DEBUG的时候总是重试,不是0吗,0就不用重试啊。为什么还是调用了多次呢? 结果在网上看到 这篇文章才明白 https://www.cnblogs....

奋斗的小牛
昨天
0
0
数据结构与算法3

要抓紧喽~~~~~~~放羊的孩纸回来喽 LowArray类和LowArrayApp类 程序将一个普通的Java数组封装在LowArray类中。类中的数组隐藏了起来,它是私有的,所以只有类自己的方法才能访问他。 LowArray...

沉迷于编程的小菜菜
昨天
0
0
spring boot应用测试框架介绍

一、spring boot应用测试存在的问题 官方提供的测试框架spring-boot-test-starter,虽然提供了很多功能(junit、spring test、assertj、hamcrest、mockito、jsonassert、jsonpath),但是在数...

yangjianzhou
昨天
0
0
rsync工具介绍/rsync通过ssh同步

rsync工具介绍 数据备份是必不可少,在Linux系统下数据备份的工具很多,其中重点介绍就是rsync工具,rsync不仅可以远程同步数据,还可以本地同步数据,且不会覆盖以前的数据在已经存在的数据...

Hi_Yolks
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部