《程序员的逻辑学》
文章摘要
《Logic for Programmers》是形式化方法专家 Hillel Wayne 历时五年完成的新书,副标题是「一本关于数学、软件,以及用前者修复后者的书」。全书 227 页、约五万字,面向在职程序员,明确声明不需要数学背景。电子版包含 PDF 和 EPUB 且无 DRM,印刷版在亚马逊发售(内容相同,只是黑白印刷、页边距更宽),官网还提供免费的样章。
作者对这本书的定位很清楚:它是关于如何更好地设计、验证和推理软件的书,而它的切入点是——学一点逻辑(也就是布尔值的数学)就能解锁我们这一行里各种很酷的技术。
书中的所有内容都以实用为目标。前几章讲的是「简化条件判断」「确保 API 变更不会破坏客户端」这类日常问题;后面的章节逐渐进入稍微冷门的领域,比如「在假想的软件设计中找出竞态条件」「最小化分布式任务的墙钟时间」。作者坦承不是所有内容对所有人都有用,但希望每个人都能找到对自己有用的部分。
关于前置知识:读者只需要具备程序员日常经验中形成的布尔 AND/OR/NOT 直觉,其余的数学书里都会补上。但你确实需要会编程——这本书面向中级到高级程序员,默认读者了解循环、版本控制、测试这些通用主题,某些章节还需要 SQL 或 API 设计的具体知识。不过各章相互独立,不合口味的可以直接跳过。
书名里那两个奇怪的字母来自逻辑符号 ∀(对所有)和 ∃(存在)。为了降低学习门槛并方便全文搜索,作者在书中用英文词代替了数学符号——比如「每个人都有一种最喜欢的颜色」写成 all p in People: (some c in Color: IsFavoriteColor(p, c)) 而不是符号形式。
完整的目录及对应技术如下:
- 逻辑速成——谓词、布尔值、集合与量词
- 重构代码——重写规则
- 写更好的测试——属性测试(property testing)
- 正确地组合代码——契约、子类型
- 证明代码正确——形式化验证、Dafny
- 处理数据——数据库理论
- 解码决策——决策表
- 建模领域——形式化规约、Alloy
- 设计系统——时序逻辑、TLA+
- 解决数学问题——约束求解与 SMT
- 逻辑编程——Prolog 与答案集编程
外加数学记号、常用重写规则和逻辑进阶话题的附录。所有代码示例都在 GitHub 上,另有一批同主题但未收入书中的额外示例。作者还专门维护了一个「额外学分」(extra credit)仓库,收录那些有趣但不够聚焦、放不进正书的话题(如如何计算状态空间大小、偏序理论等),大约四千字,书中有链接指向。
官网的 FAQ 里还顺手回答了一个经典困惑:为什么 Python 里 all([]) 等于 True?作者的解释是从性质出发的——我们希望对任意两个列表都有 all(xs . ys) == all(xs) && all(ys),如果取 ys 为空列表,那么当 all([]) 为 True 时等式退化为恒真;而如果 all([]) 为 False,就会推出 all(xs) 无论如何都是 False。原因在于 True 是 && 的单位元。同样的论证也解释了为什么空列表的和是 0、空列表的 any 是 False。
作者本人专精形式化方法、分布式系统和软件史,此前著有《Practical TLA+》和 The Crossover Project,曾为 NASA、Meta、麦肯锡、西门子、西部数据等客户做过形式化验证与培训。
HN 评论精华
这条讨论(217 分、47 条评论)整体正面且友善,除了对书本身的祝贺外,最有价值的部分是一场关于「这本书该不该更理论化」的分歧。
- rmunn 的开帖最受欢迎,讲的是一段个人经历:他大学时纯粹出于兴趣选了几门哲学课,结果发现别人在符号逻辑课上苦苦挣扎,他却觉得很轻松——因为在符号逻辑里串起一个证明,感觉和编程是同一套心智动作:你有起始条件,有想到达的终点,需要把基本操作串起来。有时候你还要学会拆解:如果要证明 P AND Q,那么分别证明 P 和 Q 通常更容易,”这感觉很像把一个做两件事的大函数重构成两个各做一件事的小函数”。他说这本书看起来正好是把这件事颠倒过来:不是用编程知识让符号逻辑变简单,而是用逻辑知识让编程变简单。
- leonidasrup 顺势指出这不只是类比而是同一件事,即 Curry–Howard 对应。但 layer8 提出了一个务实的限定:”这并不是同一件事,尤其当你用的是动态类型语言、有可变状态、并行和无限循环的时候。Curry–Howard 对应只在有限意义上适用于实际程序。这就是为什么一个高产的程序员可能依然无法构造出有效的证明。”他补充说自己非常支持编程应尽可能包含证明,但那是要努力的方向,不是既成事实。
- js8 由此展开了整条讨论中最长的一支批评:他觉得今天任何有这种抱负的作品都不应省略 Curry–Howard 同构、命题即类型,以及由此得出的逻辑与 lambda 演算之间的类比。他认为这些推论意义深远:不需要把经典逻辑当作一门独立的元语言,程序的性质完全可以用你选择的编程语言来表达;而且它表明「运行程序」和「推理程序」最终是同一个过程,这对测试等实践提出了很好的哲学问题。他希望程序员能把编程想成一门统一的语言,各种编程语言(和逻辑)只是它的不同表达,”我认为这会让元编程和形式化方法达到前所未有的规模”。
- 但他遭到了反驳。cubefox 指出他推荐的那篇论文恰好是这本书的反面——零代码的抽象学术数学(”除非你认为构造性证明就是代码。它们不是,除非写在 Lean 这样真正的编程语言里”)。LudwigNagasena 问得更直接:”什么抱负?这本书是给连 ∃ 是什么都不知道的人写的应用型入门,200 页,顶多相当于一门一学期的课。”js8 承认对方可能是对的,”但我希望有人能证明我错”。
- kriro 提出了另一条批评路线:目录里看不到哥德尔不完备定理或相关的局限性讨论,”这不是个好兆头”。他更推荐 Tarski 的《Introduction to Logic》和 Hunter 的《Metalogic》,或者干脆直接上 Prolog(《The Art of Prolog》《The Craft of Prolog》)。fmajid 反问:”哥德尔不完备定理和在职程序员有什么关系?”xelxebar 给出了本帖最好的一条技术回答:程序即数据。不完备定理、停机问题、Rice 定理的证明都共享同一个对角化结构,关键词是 Lawvere 不动点定理。他说自己不确定不完备定理本身能直接用在软件开发上,但脑子里装着几个对角化证明的例子,会让 Lawvere 结构变得显而易见;由于证明就是程序,这个模式的普遍程度令人惊讶——Futamura 投影就是它的一个化身,而这本质上正是许多解释器把程序「编译」成独立二进制的方式。cubefox 则更干脆:”那两本书不是给程序员写的,完全不同,不是替代品。而且不完备定理对程序员来说大概是无关的。”
- epolanski 的一条评论精准地总结了这场分歧:”读这个帖子里的一些评论有点让人沮丧:一半人抱怨这本书不够抽象和一般化的数学,另一半抱怨它计算机科学太多、不够纯讲写代码。这恰恰说明这本书对那些想学一点计算机科学的程序员来说完美对口。也许是个小众,但那是一个真实存在的受众。”cubefox 附议:市面上有无数干巴巴的 LaTeX 逻辑学术著作(逻辑学家最爱写关于逻辑的抽象书),毫无编程应用,但像这样的书非常稀少。
- Merkur 读完免费部分后给了一条诚实的保留意见:内容有意思,但正如作者承诺的,数学血统很浓;”它似乎偏爱那种紧凑高效的代码——而这种代码在一个能力平平的初级开发者手里、或者在一个多任务缠身的资深开发者手里是很脆的。我喜欢在有趣的项目里写聪明的代码,但在工作上我更喜欢读起来快、推理起来快的代码,别耍花招。所以我猜这是一本会挑战我既有假设的书。我喜欢这一点。”这引出了一条关于 Kernighan 定律的支线(”调试的难度是写程序的两倍,所以如果你写的时候用尽了全部聪明,你要怎么调试它?”)。dwattttt 想了想为什么这句话让他不舒服,结论是”它暗示你无法认识自己的极限——我知道这是在解释笑话,但如果你已经到了调试不动的地步,那你早就冲过『聪明』了”。jpollock 反问:在团队开发里,这不是变成了团队的平均水平吗?否则就只有你能修你自己的代码,变成了公交车因子问题。Jach 则认为团队的极限(哪怕坚持任何代码至少有两个人能修)远高于团队的平均值,而且如果代码永远不写在平均线以上,平均值也不会提高——他建议通过代码评审、代码走查、午餐分享、读书会、请顾问来教等方式提升团队。
- theusus 担心自出版会导致文字编辑质量差。harperlee 贴出了作者邮件列表里的原话作为反驳:这本书标志着一个耗时五年的项目完成,动用了六位图书出版专业人士、十四位领域专家和十五次公开 alpha。作者说这毫无疑问是他做过最大也最累的项目,光是废弃草稿里的例子就够再写一本书,而他在 LaTeX 和排版上积累的「诅咒知识」够写第三本(或至少几篇有趣的博文);”自出版同时是我做过最糟和最好的决定。现在容我睡上一个月”。Obscurity4340 的回复很暖:”睡个好觉,王,你应得这份休息。”
- 几条更轻的:gitowiec 说他想买,但「简化条件」那部分的例子读不懂,不知道适用什么规则,问有没有别的书讲这些;jibal 答唯一不那么显然的就是德摩根律,Jach 则说这大概正是第一章的作用,并点出样章选择的两难——如果放第一章,已经熟悉规则的人会失望;不放第一章,不懂规则的人又跟不上应用。mirrorlake 说自己预购了,”我常听到有学位的人后悔自己没把这本书里的材料学好,所以对很多人来说这是一个把这些技能真正练起来的机会——他们的 CS/数学/物理/工程学位并没有真的让他们做到这一点”。nxdmum 说自己把作者的 TLA+ 书做了两遍。foobarbecue 和 chris_wot 都报告了购买流程的 bug(亚马逊结账异常、Leanpub 加不进购物车),前者后来更新说问题自行修复、成功买到了印刷版。rtrigoso 则表示很想支持但拒绝在亚马逊买东西。
- altmanaltman 注意到网站页脚写着「HTML 由 Claude 生成」,于是提了一个纯粹好奇的问题:那 CSS 是谁写的?JS 是谁写的?如果全部在一个文件里,还能叫 HTML 代码吗?这引出一小段关于单文件 SPA 该如何称呼的玩笑讨论。