写给前端工程师看的函数式编程对话(系列文章)

2021-03-14 12:52:44 +08:00
 FrankFang128

第 0 天

学生:方,我理解不了数据不可变。

方:正常,我在学 Haskell 之前也理解不了。

学生:你的意思是,我要真正理解数据不可变,就必须学 Haskell ?

方:也不一定非得是 Haskell,任何一门「支持函数式」且推崇「数据不可变」的编程语言都可以。

学生:为什么,用 JS 就理解不了吗?

方:可以这么说,至少我无法用 JS 来讲解函数式,可能是我水平不够。

学生:那么我学会 Haskell 就能理解数据不可变吗?

方:不是这样的。

学生:什么意思?

方:Haskell 能发挥「数据不可变」的优势,这样你才会觉得「数据不可变」是好东西。另外,数据不可变不需要理解,这只是一个约定。

学生:约定?

方:是的,你以前学的编程语言约定「数据可变」,并且向你展示了「数据可变」的优势。

学生:对啊,我觉得数据可变才是正常的。

方:其实不是,你只是先入为主而已。你没发现数据可变的短板而已。

学生:短板是什么?

方:你现在不会认为这些短板是短板,因为你还没有见过「数据不可变」的长处。

学生:我确实没见过它的好处。我觉得它多此一举。

方:这就是问题所在,你不会认同「无副作用」「引用透明」「纯函数」是优点,你目前认为这些概念是硬凑出来的概念,对不对。

学生:是……

方:你被目前的计算机教育给局限了。你知道面向对象、图灵机,但不知道邱奇数、lambda 演算、Y 组合子,但是他们是同样重要的。

学生:确实是第一次听说……

方:那么,你想学函数式吗?

学生:学完有什么好处?

方:没有,只是拓宽你的思维,你可能依然继续用 JS 或者 Java 编程,很少用到这些技术。那么,你还想学函数式吗?

学生:你要花多久讲完?

方:你学会并习惯指令式编程语言,比如 JS 或者 Java,用了多久?

学生:大半年。

方:那么你至少需要同样长的时间才能习惯函数式,而且习惯之后就回不去了。我可能讲一段话,你要花一周甚至更久才能理解。你还想学函数式吗?

学生:听起来弊大于利?

方:我保证利大于弊,只不过短期内看不到利而已,学完之后你对编程会有完全不同的认识,但工资不一定涨。

学生:好吧,那我试试看,想学一学。

方:我们明天开始第一课。

5204 次点击
所在节点    分享创造
34 条回复
FrankFang128
2021-03-20 23:12:35 +08:00
@cyrbuzz 唉,你白看了 :(
NPC666
2021-03-21 20:31:34 +08:00
厉害厉害,醍醐灌顶
xml123
2021-03-22 18:14:13 +08:00
难得一见的教程贴,感谢 lz,只可惜 v2 这个平台不太适合做这种连载性质的内容
Chingim
2021-03-23 20:28:07 +08:00
用函数式的思想编写 js 代码, 有两个问题很困惑, 请先生教我:
1. 提倡纯函数, 导致函数的参数特别长. 更恼人的是, 层层调用的函数, 虽然只有最里层的函数需要某个参数, 外面 n 层的函数的参数列表都不得不加上这个参数. 这种场景如何解决
2. 如何隔离副作用. 一个典型的前端场景: 获取远端数据, 渲染到 dom 节点上, 点击刷新按钮, 重新获取数据进行渲染, 几乎都是副作用. 这个场景下的函数式代码是长什么样子的?
FrankFang128
2021-03-24 01:11:38 +08:00
@Chingim 1. Haskell 会自动简化这种情况,f a b c d 等价与 f(a)(b)(c)(d) 所以你需要换一门语言 2. React 的 useEffect 就是隔离副作用的例子,它让副作用全部都在 useEffect 的第一个参数里
FrankFang128
2021-03-24 01:16:17 +08:00
@Chingim 你说的 「虽然只有最里层的函数需要某个参数, 外面 n 层的函数的参数列表都不得不加上这个参数」这个问题指令式编程语言也存在,比如 C 语言的 f(null, null ,null, null, null, 'hi') 为了传 'hi' 不得不先传 5 个 null,指令式编程的解决办法是把所有参数都绑到对象上,比如 obj.a = 'a'; obj.b = 'b'; obj.addAB();
那么函数式也有对应的写法 const afterCallA = f(a); const afterCallB = afterCallA(b); const getAB = afterCallB()

我不清楚我回答的是不是你问的,如果有代码例子给我看就更好了。
Chingim
2021-03-24 11:16:14 +08:00
FrankFang128
2021-03-24 13:44:52 +08:00
Chingim
2021-03-24 15:03:07 +08:00
@FrankFang128 懂了, 就是把“传递 inner 函数需要的参数”变成“传递 inner 函数”

谢谢
DrakeXiang
2021-03-25 23:41:41 +08:00
我的思路真的是跟学生一模一样。。
DaguguJ
2021-03-26 12:16:28 +08:00
讲得 lisp 的编程风格,对吧
cyrbuzz
2021-09-13 16:46:13 +08:00
半年后又读了几遍,收益很多,感谢~。
vaporSpace
2021-12-11 20:54:25 +08:00
受益良多
cjydawn
2022-01-29 13:23:43 +08:00
受益良多,感谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/761482

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX