函数式编程到底值得学吗?为什么很多人尝试之后半途而废?undefined我自己就放弃过两次。但回头看,这两次“失败”,反而成了我编程路上的重要财富。
* * *
我写 Python 已经三年多了,习惯了简洁优雅的语法,也喜欢那种“写出来就能跑”的直接。
但总能在社区里听到一种声音:
函数式编程(FP)才是真正的优雅。undefined它纯粹、它无 bug,它能改变你写代码的方式。
于是,我挑了最“纯”的语言——Haskell。
我的预期:
现实:
Monad
才能在屏幕上输出一句话。map
、foldr
。举个例子,在 Python 里写个问候:
def greet(name):
print(f"Hello, {name}")
而在 Haskell 里,我不得不写成:
main = do
putStrLn "Enter your name:"
name <- getLine
putStrLn ("Hello, " ++ name)
为了理解这几行,我还得先啃一堆抽象概念:monad、IO、纯函数与副作用。
结果就是——我写了两周,还没能搭出一个能跑的项目。
我感觉自己不是在学写代码,而是在读一门数学系的高等代数课。
于是,第一次放弃。
我告诉自己:“也许函数式编程不适合我。”
* * *
半年后,我不甘心,又决定再给 FP 一次机会。
这次的对象是 Elixir。
为什么是它?
刚上手的时候,我很喜欢它:
defmodule Greet do
def hello(name) do
IO.puts("Hello, #{name}")
end
end
比 Haskell 那套 Monad
要直观多了。
而且 模式匹配 和 管道操作符 让我眼前一亮:
[1, 2, 3, 4]
|> Enum.map(&(&1 * 2))
|> Enum.filter(&(&1 > 4))
这段代码意思是:
取一个列表 → 每个元素乘以 2 → 过滤掉小于等于 4 的数。
简洁、优雅,一气呵成。
但我依然卡住了。
卡在 不可变性。
在 Python 里,我每天都写上百次:
x = 10
x = x + 1
可在 Elixir 里,这行会直接报错:
x = 10
x = x + 1 # ❌ cannot rebind x
在 Elixir 中,变量一旦绑定,就不能修改。
每次“更新”,都要返回一个新变量。
这完全颠覆了我对“程序运行”的直觉。
于是,在经过几天的思想挣扎之后,我再次选择了放弃。
* * *
后来我慢慢想明白:
函数式编程不是语法上的变化,而是思维方式的转变。
> 设置一个变量 → 修改它 → 在循环中继续修改它。
> 给输入 → 返回输出,不允许偷偷改变外部世界。
你必须把“变量”看作不可变值,把“流程”看作数据转换的管道。
这对大多数程序员来说,简直就是大脑重塑。
* * *
虽然我没有坚持用 Haskell 或 Elixir 写项目,但这两次经历让我收获巨大。
1. 纯函数的好处
2. 不可变性的价值
3. 你不必 100% 函数式
map
、filter
、列表推导式。* * *
在 Reddit 上,关于 Elixir vs Go 的讨论很有意思。
很多程序员提到:
一句话总结:
Elixir 更像是写“长期在线的高并发系统”,Go 更像是写“工具、基础设施与 CPU 密集任务”。
这也解释了为什么很多人尝试 FP 后会退缩:
它的学习曲线确实陡峭,也并非所有项目都需要它的“数学式优雅”。
* * *
如果你也想尝试 FP,我给几个小建议:
它太学术了,入门容易劝退。
可以考虑 Scala(对 Python 程序员更友好),或者 Elixir(语法更直观)。
进一步想要强类型 + BEAM,可以试试 Gleam。
在 Python、Java、Go 里用纯函数、不可变思路,就能收获一部分好处:
很多时候,劝退点不是语言本身,而是“装环境”。
我后来用Servbay这类本地多语言环境管理工具,体验就顺畅许多:
对于“想尝鲜但又怕折腾环境”的同学,这是非常现实的解法:先在熟悉语言里引入 FP 风格,再把小实验迁到 Elixir/Scala/Gleam,对比体会差异与收益。
* * *
如果你已经能在日常编码中自觉地“少副作用、重不可变、用纯函数”,下一步可以考虑把 FP 落到团队工程实践里:
- 约定:业务函数默认纯函数,I/O、副作用集中在接口层。
- 结构:小函数 + 组合优先,避免巨石函数;
- 数据:不可变数据结构优先(即便语言不强制,也尽量不原地修改)。
- 纯函数单测覆盖率高,Mock 难度低;
- 副作用在边界,端到端测试专注流程正确性。
- Go 场景:goroutine + channel 的约定式并发,配合 context 超时与 errgroup;
- Elixir 场景:OTP 的 supervision tree、进程隔离与自愈,天然容错。
- Go:静态编译、单文件交付,容器化与多架构镜像更省心;
- Elixir:考虑 release、节点编排与可观测性,充分利用 OTP 的能力。
- 通过 code review 强化“无副作用边界”的习惯;
- 为新人准备 FP 风格的代码范例与重构清单;
- 从“小而确定”的模块开始推广(比如纯函数的定价、折扣、风控规则)。
* * *
我两次放弃了函数式编程,但我依然感谢它。
因为它让我更清楚地认识到:
别焦虑于“学不会” 。
哪怕只学到“写纯函数、少用副作用、尊重不可变”,你已经在向更专业的工程师靠拢。
至于要不要上手 Elixir/Haskell/Scala?不妨先在熟悉的语言里用起来,再用 ServBay 搭个本地实验场,循序渐进,择其善者而从之。
* * *
欢迎在评论区分享你的故事与实践。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。