思考并回答以下问题:
- function a() { return (function(){}); }返回什么类型?
- 第一等公民是什么意思?
- 只用“表达式”,不用“语句”是什么意思?
- 闭包和函数式编程密切相关,可以说函数式编程就是闭包。怎么理解?
- 只要函数里有相同代码就可以使用闭包,尤其是if else里面有相同的代码。怎么理解?
处理一个数组。
1 |
|
最终都是返回Generator生成器。
常见写法
1 | /** |
常规函数
1 | $data = function ($results) |
闭包
1 | $data = function () use ($results) |
抽象写法
1 | /** |
函数式编程
闭包closure是函数式编程。
闭包可以理解成“定义在一个函数内部的函数”。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
实现同样的功能函数式编程所需要的代码比面向对象编程要少很多,代码更加简洁明晰。
函数式编程的特点:函数可以赋给变量,所以,可作为参数传递,可作为返回值返回。PHP返回闭包。
array_walk、array_map等都是函数式编程。
什么是函数式编程
与面向对象编程(Object-oriented programming)和过程式编程(Procedural programming)并列的编程范式。
最主要的特征是,函数是第一等公民。
强调将计算过程分解成可复用的函数,典型例子就是map方法和reduce方法组合而成的MapReduce算法。
只有纯的、没有副作用的函数,才是合格的函数。
PHP中的函数
例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17$grade = [
[
'id' => 1,
'subject' => 'chinese',
'score' => 82
],
[
'id' => 2,
'subject' => 'math',
'score' => 98
],
[
'id' => 3,
'subject' => 'english',
'score' => 78
],
];
array_filter — 用回调函数过滤数组中的单元
1 | // 获取成绩大于80分的学科 |
array_map() - 为数组的每个元素应用回调函数
1 | // 不影响原数组,返回一个新数组 |
array_reduce() - 用回调函数迭代地将数组简化为单一的值
1 | // 求分数最高的科目,返回最大科目信息 |
array_walk() - 使用用户自定义函数对数组中的每个元素做回调处理
1 | // 修改原数组 |
定义
简单说,“函数式编程”是一种“编程范式”(programming paradigm),也就是如何编写程序的方法论。它属于“结构化编程”的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用。
函数编程式是一种编程风格,它将关注点从执行命令转移到表达式计算。这些表达式是使用函数构成的,结合这些函数可以得到我们要查找的结果。
闭包通常出现在允许将函数处理为第一类值(First-class value)的语言中,这意味着函数可以动态创建并作为参数传递给其他语言。
函数式编程的特点
函数是“第一等公民”
所谓“第一等公民”(first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。
只用“表达式”,不用“语句”
“表达式”(expression)是一个单纯的运算过程,总是有返回值;“语句”(statement)是执行某种操作,没有返回值。函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。
原因是函数式编程的开发动机,一开始就是为了处理运算(computation),不考虑系统的读写(I/O)。“语句”属于对系统的读写操作,所以就被排斥在外。
当然,实际应用中,不做I/O是不可能的。因此,编程过程中,函数式编程只要求把I/O限制到最小,不要有不必要的读写行为,保持计算过程的单纯性。
函数式编程不依赖、也不会改变外界的状态,只要给定输入参数,返回的结果必定相同。因此,每一个函数都可以被看做独立单元,很有利于进行单元测试(unit testing)和除错(debugging),以及模块化组合。
副作用
所谓“副作用”,指的是函数内部与外部互动(最典型的情况,就是修改全局变量的值),产生运算以外的其他结果。在纯函数式语言中,函数只能读取其参数提供给它的内容,并且它对世界产生影响的唯一方式就是通过它返回的值。
递归和迭代
对于函数式而言,循环体有一个无法避免的副作用,就是它会修改某些对象的状态,通常这些对象又是和其他部分共享的。而且也因为变量值是不可变的,纯函数编程语言也无法实现循环。
所以纯函数编程语言通常不包含像while和for这样的迭代构造器,而是采用的无需修改的递归。