首页 › programming › 函数式不难:40分钟看懂三根柱子

函数式不难:40分钟看懂三根柱子

导语

每个程序员都经历过这种灵异事件:你只改了一行代码,另一个八竿子打不着的模块突然崩了。排查一整晚,最后发现罪魁祸首是某个被悄悄改写的全局变量、某段"顺手更新"的共享状态。这类 bug 的学名,叫隐式状态失控——它不是你的水平问题,而是命令式编程的先天体质。

而函数式编程(Functional Programming),恰恰是给这个病开的药方。可惜它在中文互联网上的形象长期被妖魔化:要么是"Monad 玄学,学了没用",要么是"学院派玩具,工业界不待见"。Russ Olsen 在 GOTO 大会的这场演讲 《Functional Programming in 40 Minutes》,就是治这种偏见的解药。他不教你任何一门语言,不推导任何数学定理,而是用 40 分钟把一件事讲透:函数式为什么会出现?它治的是命令式编程的什么病?三根支柱到底是什么?

在 AI 大量生成代码、多核并发无处不在的 2026 年,这套"让代码可推理"的思维方式,比任何时候都更值钱。

视频背景卡片

项目 内容
视频标题 Functional Programming in 40 Minutes
频道 GOTO Conferences(全球顶级软件技术大会官方频道)
演讲者 Russ Olsen(《Eloquent Ruby》《Getting Clojure》作者)
时长 约40分钟
发布 GOTO 大会场次(官方频道版本,站内早前调研记录为 2024 年场次)
播放量 数十万级(官方频道多年沉淀,精确数据以频道页面为准)
核心主题 用思想史视角讲清函数式编程的三大支柱与工程价值

核心内容拆解

1. 先诊断:bug 的最大温床是隐式状态

Olsen 的开场不是定义,而是诊断。命令式编程的默认动作是改数据:声明一个变量,然后一路修改它。程序越长,"这个变量此刻到底等于几"就越说不清——十个人改过它,十处分支碰过它,它的状态散落在整个调用链里。这就是隐式状态:数据怎么变的,代码没有明说,全靠你脑内模拟。

延伸一点:这正是生产事故里最难缠的一类问题的根源。状态竞态、脏读、缓存不一致、UI 与数据不同步,往下挖几乎都能挖到"共享可变数据"这块石头。Olsen 在演讲中的核心论点也在这里:函数式代码之所以更可靠、更易并行、更易测试,是因为它从源头消除了隐式状态这个 bug 温床——不是靠更聪明的调试工具,而是靠让"数据怎么变"这件事在代码里无处躲藏。

2. 支柱一:纯函数——同输入必同输出

第一根支柱是纯函数(Pure Function):给定相同输入,永远返回相同输出,并且不碰函数体以外的任何东西——不读全局变量、不改参数、不写数据库、不打印日志。一句话总结视频里的标准:函数像数学函数,而不是"过程"。

这个约束看似苛刻,回报却极其丰厚。首先是测试变得近乎免费:你不需要 mock 半天环境,构造输入、断言输出,完事。其次是引用透明:f(3) 只要算过一次,永远可以替换成它的返回值,这让缓存(记忆化)和并行化变成编译器随手可做的优化。最后是可读性:读一个纯函数,不需要理解它的 500 行上下文,函数签名就是全部真相。

延伸一点:团队协作里这个特性被严重低估——纯函数的 code review 速度是普通代码的好几倍,因为审查者不需要在脑内模拟状态机。

3. 支柱二:不可变数据——别改,去造新的

第二根支柱是不可变性(Immutability):数据一旦创建,就不再修改;要"改",就基于旧值造一份新副本。听起来浪费内存?Olsen 用类比说明的正是这一点:可变数据像一块大家共用的白板,谁都能擦谁都能写,出了问题没人认账;不可变数据像一沓打印纸,每一版都有据可查,diff 和回滚都是天然的。

工程世界其实早就用投票表达了这个思想的正确性:Git 的每一次 commit 都是对完整快照的引用,从不原地修改历史;React 要求状态"替换"而非"变异",Redux 干脆把整个应用状态变成一棵只读树;Java 的 String 从 1995 年起就是不可变的。这些系统无一例外都因此获得了免费的一致性保证。

延伸一点:不可变性最深的红利在并发——数据没人能改,就不需要锁;不需要锁,就没有死锁和竞态。多核时代的并发难题,被这根支柱直接降维。

4. 支柱三:函数是一等公民——代码也是积木

第三根支柱是函数一等公民(First-Class Functions):函数可以像数字、字符串一样,被当作参数传入、当作返回值返回、存进变量里。于是出现了高阶函数——接收函数的函数。map、filter、reduce 三件套就是最经典的产物:一个函数负责"对每个元素做什么",另一个负责"筛选什么",变换逻辑成了可以自由传递的零件。

演讲在这里给出了一个重要的视角转换:写循环时,你在描述"怎么一步步做"(先取下标,再判断,再赋值);用高阶函数时,你声明的是"做什么"(把每个订单映射成金额,再过滤出大于一百的)。代码从操作手册变成了组合说明书,而组合,正是控制复杂度最古老也最有效的手段——乐高之所以能搭出一切,靠的不是每块积木更复杂,而是接口足够标准。

5. 思想史:比 C 语言还早 14 年的想法

这场演讲最与众不同的地方,是它站在思想史的高度俯瞰整个范式之争。这条时间线值得单独抄下来:

时间 里程碑 意义
1930年代 Church 提出 λ 演算 函数式编程的数学地基
1958年 McCarthy 设计 Lisp λ 演算第一次变成可运行的代码
1977年 Backus 图灵奖演讲 公开质疑冯·诺依曼风格,为范式正名
1990年代 Haskell、ML 系谱成熟 纯函数式语言学完善(Okasaki 1998 年出版纯函数式数据结构)
2005年前后 "免费午餐结束",多核普及 并发压力让不可变性重回聚光灯
2011-2014年 C++11、Java 8 相继引入 Lambda 函数式思想全面渗入主流语言

看懂这条线,你就明白一个反直觉的事实:函数式不是对命令式的"新颠覆",它比绝大多数在用的编程语言都老。它不是没赢,而是化整为零——你没有写 Haskell,但你每天写的 Stream API、箭头函数、列表推导式、只读状态树,全都是它的思想遗产。

6. 范式不是宗教:Olsen 的务实态度

很多 FP 讲座的潜台词是"你应该抛弃现有的一切",Olsen 明确不站队这种立场。他本人的技术轨迹——从 Ruby 社区的《Eloquent Ruby》到 Clojure 社区的《Getting Clojure》——就是一条渐进路线:不换赛道,而是把函数式思维当作工具箱里的工具,按需取用。

演讲传递的态度可以概括为三句话:不必重写成 Haskell;新代码从"默认不可变、副作用收拢到边界"开始,就已经吃到八成红利;判断一个团队是否真的理解函数式,不看它用什么语言,看它的代码里还有多少"说不清从哪来的状态"。

延伸一点:这种"渐进采纳"的务实感,正是这场演讲和 Monad 猫咪图解流的本质区别——它面向的不是语言发烧友,而是每天要在遗留系统里讨生活的工程师。

7. 为什么是现在:多核与 AI 时代

视频的最后把镜头拉回当下,而这个论点在 2026 年只强不弱。

多核侧:单核性能早已停止狂奔,并行是唯一的免费午餐。而并行的最大敌人恰恰是共享可变状态——三根支柱中的不可变性,几乎是为此量身定做的答案。

AI 侧(这部分是我的延伸,视频未展开):AI 批量生成代码的今天,人类的核心工作正在从"写代码"转向"读代码、验代码、定规格"。什么样的代码最容易被验证?纯函数。签名即规格,输入输出即验收标准,AI 生成纯函数的准确率和可审查性远高于随手改状态的命令式长函数。可以说,函数式三根支柱,就是 AI 协作时代最好的"代码验收接口"。

知识结构图

flowchart TD
    A["命令式习惯<br/>随手改数据"] --> B["隐式状态泛滥"]
    B --> C["难测试"]
    B --> D["难并发"]
    B --> E["难排查"]
    B -->|换范式| F["函数式三支柱"]
    F --> G["纯函数"]
    F --> H["不可变数据"]
    F --> I["函数一等公民"]
    G --> J["同输入<br/>必同输出"]
    J --> K["易测试易缓存"]
    H --> L["改动即造副本"]
    L --> M["无别名<br/>并发免锁"]
    I --> N["高阶函数"]
    N --> O["map与filter<br/>组合复用"]
    K --> P["复杂度显式化"]
    M --> P
    O --> P

实战启示

看完这场演讲,你不需要任何"宏大迁移",明天就能在现有语言里执行三条纪律:

第一,默认不可变。 Java 用 final、JS 优先 const 配合展开运算、Python 用 tuple 和 frozenset、Rust 干脆把可变性做成需要显式声明的特权。凡是要"改"一个集合的地方,先问一句:能不能返回一个新的?这一条纪律能消灭你代码库里相当大比例的"幽灵 bug"。

第二,把副作用推到边界。 业务核心全部写成纯函数,数据库读写、网络请求、日志打印这些"不干净"的操作,集中收拢到最外层薄薄一层壳里。核心逻辑因此可以脱离环境测试,出问题时排查范围直接缩小一个量级。

第三,用声明式三件套替换手写状态循环。 能用 map/filter/reduce 表达的变换,就不要用"临时变量 + for 循环 + 中途赋值"。不是为了炫技,而是因为声明式代码里,数据的流向写在脸上。

对技术管理者,多送一句:团队里关于"代码怎么才可靠"的争论,往往在范式层面就注定吵不出结果。这场 40 分钟的视频,是我见过最好的团队认知对齐材料——它不要求任何人改变技术栈,只要求所有人理解同一套"复杂度从哪来"的语言。

延伸学习路径

  1. Scott Wlaschin《Domain Modeling Made Functional》(GOTO) — 把函数式思维落到领域建模实战,F# 讲得像散文,是本篇最佳的"下一步"。
  2. Russ Olsen《Getting Clojure》 — 演讲者亲笔,用一门现代 Lisp 把三大支柱落到实处,文字风格和演讲一样松弛幽默。
  3. Computerphile 频道的 Lambda Calculus 与 Monad 短片 — 每集十来分钟,把本篇点到为止的数学地基补齐,与 Nottingham 的 Graham Hutton 系列同源,适合加餐。
  4. Paul Graham《Beating the Averages》(2001) — 把"用可生长的语言"讲成商业竞争战略的经典长文,与本篇的思想史视角互为表里。
  5. Bartosz Milewski《Category Theory for Programmers》 — 当你不再害怕"范畴论"三个字之后的进阶读物,书与视频课皆可免费获取。

一句话总结

函数式编程不是让你换一门语言,而是让你在任何语言里少埋雷——纯函数、不可变、可组合这三根柱子,撑起的是"代码可以被推理"这个工业软件最贵的奢侈品。

参考来源

  1. Functional Programming in 40 Minutes — Russ Olsen, GOTO Conferences — 本文分析的核心视频
  2. Domain Modeling Made Functional — Scott Wlaschin(GOTO) — 函数式领域建模实战延伸
  3. Simple Made Easy — InfoQ 完整版页面(Rich Hickey) — 同一思想脉络下关于"简单与容易"的经典姊妹篇

本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入