理解函数式编程的本质

functional programming

前言

笔者在之前曾经花时间学习了Haskell(所谓的纯函数式编程语言),并且在也研究过一段时间的函数式响应编程,也就是Functional reactive programing,总体有直观的感觉,但最近在学习kotlin的过程中,突然对于函数式编程又引起了新的思考,于是花时间去研究了一番,究竟什么是函数式编程,总结成文希望能够帮助你理解。

一些理解存在偏差

函数式编程在各个领域经常被提及,但很多文章去讲函数式编程都会有些偏差,并没有抓到本质。或者说讲了函数编程常见的写法,但没有讲清楚究竟什么是函数式编程。只有理解了这个本质问题,才能在后续的学习中一帆风顺。

(为了理解函数式编程,本文后面一些名词直接采用英文名词进行解释说明,因为生硬的翻译过来,会加大理解的难度)

什么是函数(Function)

这个问题虽然看上去很简单,但其实并不简单。

函数(function)这个名词来自于数学,函数通过一个给定的值,计算出另外一个值,也就是上学时常见的f(x)。

在通常的理解中,下面代码里面,f1,f2,f3通常都被叫做函数:

//伪代码 函数无入参,返回2
def f1(): return 2
//函数有参数x,返回 x+1
def f2(int x): return x+1
//函数无入参,无返回值,打印hello world
def f3(): print("hello world")

但实际上,函数(function)和procedure是有区别的:
function 通过运算返回一个值,而procedure只执行一段代码,没有返回值。 这一点对于后面的理解是非常有帮助的,首先要区分出二者。

再回到上面的代码中,f1,f2,为function而f3为procedure。

什么是Pure Function

Pure:纯的; 单纯的; 纯真的; 干净的
我们将满足下面两个条件的函数称作Pure Function:

  1. 函数不会产生side effect(no side effect)
  2. 函数满足referential transparency这个条件
    (原谅我不会翻译这两个名词)

Side effect

函数调用后不会对外部状态产生影响,比如下面这段代码中sum函数是no side effect的:

def sum(a,b): return a+b

产生side effect的函数长成什么样呢?其实经常会写这样的函数:

int sum = 0
def plus(a,b){
  sum = a + b
  return sum
}

plus函数除了计算参数之和以外,还改变了外部变量sum的值,我们plus这个函数产生了side effect。

常见的Side effect

  • 改变外部变量的值(上面的例子中plus函数)
  • 像磁盘中写入数据
  • 将页面上的一个按钮设置为可点击,或者不可点击

前面提到function和procedure的不同点,在side effect这个角度来讲,pure funcion不会产生side effect,procedure通常会产生side effect。

Referential transparency

Referential transparency means that given a function and an input value, you will always receive the same output. That is to say there is no external state used in the function.

Referential transparency means that you can replace anyexpression in the program with the result of evaluating that expression (or vice versa) without changing the meaning of the program.

  • 满足Referential Transparency的函数可以将可以将用函数计算的结果替换表达式本身,而不影响程序的逻辑。
  • 给定指定的参数,在任何时候返回的值都是相同的。不受其他外部条件影响。

两者说的意思是一样的,只是表达的角度是不同的

举个满足RT的例子

def f(): return 2

print(f() + f())
print(2)

下面这段代码中的f()是满足RT的函数,按照上面的解释,我们可以将f()的结果也就是2替换掉f(),不会影响程序本身的逻辑:

def f(): return 2

print(2 + f())
print(2)

或者这样替换:

def f(): return 2

print(f() + 2)
print(2)

从另一个角度说,f()这个函数无论在什么时候调用,返回的值都是一样的,不会发生改变(没有外部条件影响)

举个不满足RT的例子

int counter = 0

def f(x){
  counter += 1
  return x + counter
}

这个例子中,f(x)这个函数不满足RT
下面的代码中,当我们用f(1)的计算结果一次替换代码中f(1)本身时,程序的逻辑是错误的:

//原始的代码执行结果是:3
f(1) + f(1)

//把f(1)的结果1替换进来,下面函数执行的结果是:2
f(1) + 1

//同样,得到2
1 + f(1)

//得到2
1 + 1

我们不能用执行的结果替换函数本身,

换个角度,下面两行代码执行的结果也不同

f(1) + f(1)
2 * f(1)

虽然入参都为1,但f(1)在不同时候调用得到的结果不同,因此f不满足RT这个条件

回到pure function

理解了side effect 和 referential transparency的含义,我们再来重温pure function的定义,就很好理解了:

  • No side effect
  • Referential transparency

满足这两个条件的函数,称之为pure function

什么是函数式编程

理解了pure function之后,我们回到什么是functional programing,就会有种豁然开朗的感觉:

Functional programming is about writing pure functions

函数式编程最大限度的写pure function,让函数最大限度的减少side effect,并且保证函数在任何时候传递相同参数时,得到的结果都相同。

有什么好处

当我们按照函数式编程的思想编写程序时,程序具有天然的模块属性,因为实现的函数为pure function,你可以任意组合这些pure function。

pure function不会产生side effect,不需要对外部的状态产生顾虑。

其他好处在很多文章中都有提到,后续有时间笔者再来分析。:-D

总结

希望通过前面几个核心概念的讲解,能够让你明白函数式编程的本质,如果有任何文中写的有偏差的地方,欢迎讨论,👏

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容