追求真空
追求真空 编程-学习-思考

函数式编程的几个特点

函数式编程的几个特点

函数式编程作为一种编程方式越来越受到人们的关注和使用,像之前的面向过程编程和面向对象编程一样,已然成为编程语言必须具备的一个功能。这里,就让我用JavaScript来说说我对它的理解。

什么是函数式编程

如果你需要理解一个事物,就必须要清楚它的概念。函数式编程并不像它字面意思上看起来那么简单,所以我们不能望文生义的使用熟悉的函数概念去理解它。虽然函数式的基本元素依然是函数,但它更多的是作为一种思想理念而存在的。和过程编程、面向对象编程一样,函数式编程也同样是为了解决程序问题而生的。但是,前俩个更多的关注于问题解决的过程方法,而函数式编程更多的关注于要解决的问题本身。即函数式编程更加强调程序执行的结果而非过程。

一个语言想要支持函数式编程,最简单的办法就是函数可以像普通变量一样的使用,可以赋值、当做参数传递和返回。Java 中引入了 lambda,而 JavaScript 和 Python 对函数式编程好像特别友好。所以用 JavaScript 来展示应该更加的清楚明白吧。

函数式编程的特点

好吧,我自己总结的几个函数式编程区别于传统编程不同的地方,如果有什么见解和意见欢迎留言共同探讨。

函数没有副作用

如果要实现函数式编程的思想,那么函数就要拥有普通变量一样的待遇。但是,函数里面有操作,有语句,有变量的赋值、改变以及其他操作。这样如果函数调用函数、到处赋值处理那么就很容易造成程序变量状态混乱不容易跟踪。

所以,最简单的解决办法是,一个函数最好不改变任何已有变量和程序的状态,它只进行一些操作,一个输入产生一个结果。不会带来任何中间状态的改变。

没有副作用的函数称为纯函数。设计纯函数的时候通常是输入一个值,然后返回一个修改的值。而不是像通常面向对象编程一样在函数里面直接修改,然后在函数之外的值就同样改变了。这样做的好处就是设计起来简单,编写起来也容易理解和调试。例如:

1
2
3
4
5
const person = {
	name: "Frederick Doo",
	canRead: false,
	canWrite: false
}

定义了一个 person 变量,如果我需要定义一个函数来改变它的状态,那么纯函数看起来就像这样的:

1
2
3
4
5
6
const selfEducate = person => 
					({
							...person,
							canRead: true,
							canWrite: true
					})

这里用函数直接赋值给变量,因为只有一个参数所以可以省略括号,而 => 符号表示 return 后面表达式,… 表示复制 person 。因此,这个函数首先复制 person 的值,然后修改或添加其中的几个参数,然后返回复制的 person ,而原来那个 person 保持不变,当然这只是一个很简单的纯函数。

关注问题而不是解决方法

这也许是函数式编程最重要的编程思想。关注问题本身而不是如何去解决问题,因为解决问题的方法已经写在了各个函数里面,而你需要做的就是如何去组合调用这些函数去实现你想要的结果和功能。

最普遍的做法就是,你已经有了实现各种功能的纯函数。像上面的把 person 改为 selfEducate 的 person,或者把一个字符串首字母大写,或者判断一串字符串是不是有效的电话号码。然后你有一组数据,想实现一些替换、查找和过滤功能,就可以直接使用数组的内置函数把这些功能函数当做参数传递进去就可以了。例如:

1
2
3
4
5
const schools = [
	"Yorktown",
	"Washington & Lee",
	"Wakefield"
]

如果你需要查找首字母为 w 的学校,那写成表达式或者函数就是:

1
begainW = school => school[0] === 'W'

那么这就是直接描述了你想要做什么,然后使用 filter 函数就行了:

1
wS = schools.filter(beginW(school))

才写两点就已经才尽了,主要是要吃晚饭了,国庆节是要吃大餐的。在此附上一个英文文献后续再更新对于函数式编程思想的理解。