Lobsters 对 Sjamaan 的访谈

Lobsters Hottest 新闻

摘要

对 Peter Bex 的访谈——他是 CHICKEN Scheme 的维护者,也是职业 Clojure 开发者。访谈内容涵盖他从 C64 BASIC 走向 Lisp 的经历、对 CHICKEN Scheme 的核心贡献(数值塔、irregex、安全修复),以及他对 Scheme 社区、Racket、Postgres 和 Clojure 的看法。

<p>我们亲爱的 <a href="https://lobste.rs/~sjamaan" rel="ugc">@sjamaan</a>(<a href="https://www.more-magic.net" rel="ugc">个人网站</a>)是 CHICKEN Scheme 的维护者,也是一名职业 Clojure 开发者。我们在 IRC 上相识几个月,聊了以下话题:</p> <ul> <li> <a href="https://call-cc.org/" rel="ugc">CHICKEN</a> Scheme 及其 6.0.0 版本的发布</li> <li>Scheme 的社区与标准化进程</li> <li>Postgres、MySQL 的种种可怕之处,以及(默认配置下的)SQLite</li> <li>Clojure</li> </ul> <blockquote> <p>我目前的核心贡献主要集中在数值塔代码、保持核心中 irregex 库的副本与上游版本(我是其共同维护者)同步、修复 bug,以及偶尔的安全补丁。我喜欢深入代码库中那些古怪的角落,以便更好地理解它,然后改进我发现的任何怪异之处。——<a href="https://wiki.call-cc.org/users/peter-bex" rel="ugc">他的 CHICKEN 简介</a></p> </blockquote> <hr> <strong>起点</strong> <p><strong>你是怎么开始接触计算机的?</strong></p> <p>我接触计算机的起点是,得到了一台别人送的旧 C64,附带一本面向儿童的"学 BASIC"教程书。当然,我当时想自己写电脑游戏(不过最终也没写成)。后来我生日时得到了一台真正的 PC,并发现我的 BASIC 知识多少能派上用场(DOS 下的 QBASIC)。</p> <p>之后我接触了 C 语言,并用了好多年,直到大学时有一门课程教 Lisp(其实是 Scheme)。我们从 The Little Lisper / The Little Schemer 开始,然后是 SICP。在那之前我还上过一门"函数式编程课",差点挂掉,因为那些内容对我来说毫无道理可言(他们用的是 Concurrent Clean——显然老师们只教自己熟悉的语言,而不管这门语言本身如何,这是学术界常见的毛病)。不过 The Little Schemer 终于让我开了窍。那位老师还演示了如何仅用 lambda 就实现对象,我觉得这太棒了。</p> <p>实际上我学的是人工智能,而且是在所有 LLM 破事发生之前。我更喜欢经典 AI 算法的巧思,比如 A* 搜索和遗传算法,但我在实践中其实没怎么用过它们,只有在学业中用过。我总觉得自己该拿遗传算法做点什么,但至今也没找到真正的用例。不过即使在那时,神经网络是未来的趋势这一点已经很清楚了,只是我觉得它们很无聊——不过就是一点数学(我最初几乎看不懂),本质上是个黑盒。我还是很感激自己学过 AI,因为正是这段经历让我接触到了 Lisp。</p> <p>我或许本来也会自己去研究 Lisp(它作为"基础语言"之一一直让我好奇),但我可能没有足够的热情去真正深挖。大学毕业后我找了一份工作,那家公司从相当早期(2006 年)就开始用 Rails,所以我也学了 Ruby。我喜欢学 Ruby,也觉得亲眼看到 Rails 的强大很酷,但后来对它非常失望,因为 Rails 的观点极其强烈,而我的编程风格似乎与它并不完全兼容。</p> <strong>CHICKEN 与 Scheme</strong> <p><strong>为什么选 CHICKEN?</strong></p> <p>那门课之后,我每个个人项目都尝试用 Lisp。一开始我用的是 Scheme48,但它不够实用(虽然非常优雅)。我记得遇到过镜像(image)不够大的问题,内存耗尽。我从来都不怎么喜欢 PLT Scheme(现在的 Racket),最初是通过 DrRacket 接触的,它给我的感觉非常迟钝,不过我确实认为 DrRacket 是对 IDE 能做什么的一种很酷的另类呈现。比如,当你把鼠标悬停在一个变量上时,它会画一条线指向这个变量的来源。</p> <p>CHICKEN 是一个实用且快速的系统,社区不错,许可证也可以接受(当时我对 GPL 相当反感)。CHICKEN 还是(据我们所知)仅有的两个使用 Cheney on the MTA 技术的实现之一,<a href="https://wiki.call-cc.org/chicken-compilation-process" rel="ugc">这里有解释</a>。它有不少毛糙的地方,但我觉得正是想要解决这些问题的念头,才让我深入到核心之中。如果一切都完美无缺,那其实就没什么可做的了!</p> <p>于是我开始为 CHICKEN 做贡献,最初是一些不太起眼的 egg(<a href="https://wiki.call-cc.org/eggs" rel="ugc">CHICKEN 的包</a>),最终深入到了核心系统。我了解 Lisp 内部原理的方式基本就是边做边学,摆弄 CHICKEN 核心,不断尝试。我读过 Queinnec 的《Lisp in Small Pieces》,它涉及编译到 C 的过程,但省略了<em>大量</em>内容,而且充斥着面向对象的东西,有些喧宾夺主。SICP 里有一些不错的材料。还有 Appel 的《Compiling with Continuations》,篇幅很短、直切要点,但依然相当全面;我就喜欢这样的书。</p> <p>总的来说,我就是喜欢钻研核心,即便如今我没有太多时间这么做。我必须强调,我是个学习很慢的人。我对 CHICKEN 建立理解是一个经历了许多年的过程,直到现在,系统中仍有一些部分我并不十分熟悉(不过我对整体足够熟悉,需要时能较快上手)。</p> <p><strong>那些 Lisp 书籍缺少了什么?</strong></p> <p>《Compiling with Continuations》对运行时系统只有简短的一节,所以它并没有深入探讨比如垃圾回收和数据表示。我记得《Lisp in Small Pieces》没有讲 continuation-passing style(续延传递风格)。而且它的数据表示也不是很优化。我喜欢<a href="https://www.more-magic.net/archive.html" rel="ugc">写博客</a>,介绍如今很少有人讨论的酷炫技巧。比如如何实现<a href="https://www.more-magic.net/posts/weak-references.html" rel="ugc">弱引用</a>,以及如何高效地对它们进行 GC。其他我很少见到讨论的话题包括如何做 FFI(外部函数接口)和跨模块优化、分离编译和交叉编译(只有极少数 Scheme 实现支持)等等。</p> <p><strong>Scheme 对你来说意味着什么?</strong></p> <p>总的来说,Scheme 对我而言是一种非常干净的语言,核心最小,便于实验。这正是标准化进程的根本张力——面向生产质量的 Scheme 往往会不断膨胀,标准化这些内容确实有价值。但这也让那些使实验性实现成为可能的极简性打了折扣。比如 Felix Winkelmann(<a href="https://lobste.rs/~bunny351" rel="ugc">@Bunny351</a>,CHICKEN 原作者,<a href="https://www.youtube.com/watch?v=VZp1wWivFYc" rel="ugc">他关于 Scheme 实现的演讲</a>)曾经开始写一个 Common Lisp(子集)实现,在其中对类型和控制流分析做了大量实验,最终形成了 CHICKEN 中的类型相关内容。</p> <p><strong>你对整个 Scheme 生态系统有什么看法?R7RS、SRFI 与各实现特有的库之间的关系等等?有几个实现似乎已经不再关心这些了。</strong></p> <p>我认为把 R7RS 拆分为小语言和大语言是正确的做法,因为 R6RS 遭到了极简主义者的唾弃,又被激进主义者认为不够完整。总体而言,我对 R7RS 有些伤感——如果一些较大的社区 Scheme 实现基本上完全无视它,那在我看来是它们做错了。很多、甚至可能是大多数 Scheme 实现基本上都是一个人在维护。我猜 CHICKEN 又开始走向这种状态了,因为我们失去了不少贡献者(大多是由于生活境况的变化),而且很难吸引新的贡献者。</p> <p>与此同时,R7RS "large" 项目某种程度上走向了极端,只顾做自己的事,不太关心社区的认同。R7RS large 的变动节奏也太快,难以跟上。他们在几年之内推出了大量 SRFI(现在回头看,似乎并没有<em>那么</em>多,但确实比过去的 SRFI 流程快得多)。SRFI 的流程向几乎任何人开放投稿
查看原文
查看缓存全文

缓存时间: 2026/10/02 22:41

# Peter Bex 谈 CHICKEN Scheme 来源:https://alexalejandre.com/interviews/peter-bex/ 2026年9月 - Alex Alejandre --- Peter Bex(个人网站 [https://www.more-magic.net/](https://www.more-magic.net/))是 CHICKEN Scheme 的维护者,也是一名职业 Clojure 开发者。我们在 IRC 上聊了几个月,话题涉及: - CHICKEN(https://call-cc.org/)Scheme 及其 6.0.0 版本 - Scheme 的社区与标准化进程 - Postgres、MySQL 的种种噩梦以及(默认的)SQLite - Clojure > 我目前对核心的主要贡献集中在数值塔(numeric tower)代码、让内置的 irregex 库与上游版本(我是该库的联合维护者之一)保持同步、修复 bug 以及偶尔的安全补丁。我喜欢深入钻研代码库中那些古怪的角落以获得更好的理解,然后改进我所发现的任何异常之处。——摘自他的 CHICKEN About 页面 [https://wiki.call-cc.org/users/peter-bex](https://wiki.call-cc.org/users/peter-bex) --- ### 起步 **你是怎么接触计算机的?** 我最初的接触是来自一台别人淘汰下来的 C64,附带一本面向儿童的"学 BASIC"手册。当然,我想自己写电脑游戏(虽然最后也没写成)。后来我生日时得到了一台真正的 PC,发现我的 BASIC 知识竟然(通过 DOS 下的 QBASIC)可以迁移过去。 再后来我接触了 C,并用了好几年。直到大学里有一门课教 Lisp(其实是 Scheme)。我们从《The Little Lisper》/《The Little Schemer》开始,然后是 SICP。在这之前我还上过一门"函数式编程"课,差点不及格,因为实在完全摸不着头脑(他们用的是 Concurrent Clean——显然老师们总是用自己的语言来教,不管那语言好不好——这是学术界的一个常见毛病)。但《The Little Schemer》最终让我开了窍。那位老师还展示了如何只用 lambda 实现对象,我觉得那太酷了。 其实在 LLM 这些破事之前,我学的是 AI。我更喜欢经典 AI 算法中那种巧妙的思路,比如 A* 搜索和遗传算法,但这些我在实际工作中很少真正用到,只在学习时用过。我一直想着应该用 GA 做点什么,但至今没有找到真正合适的场景。不过早在那时就很清楚神经网络是未来,只是我觉得它们很无聊——无非就是一些数学(我一开始几乎一窍不通),而且本质上是个黑盒。我至今仍然感激自己学过 AI,因为正是它让我接触到了 Lisp。 我可能总有一天会自己去研究 Lisp(毕竟它作为"基础语言"之一一直让我好奇),但也许当时没有足够的劲头去真正深入。大学毕业后我找了一份工作,那正是 Rails 相对早期的时期(2006 年),所以我顺便学了 Ruby。我喜欢学 Ruby,也觉得看 Rails 的威力很酷,但后来对它非常沮丧,因为 Rails 的主观性太强,而我的编程风格似乎和它并不完全兼容。 ### CHICKEN 与 Scheme **为什么选 CHICKEN?** 那门课之后,我在每个个人项目里都试着用 Lisp。最开始我用的是 Scheme48,但它不太实用(虽然非常优雅)。我记得遇到过镜像(image)不够大、内存耗尽的问题。我也一直不太喜欢 PLT Scheme(现在叫 Racket),最初接触它是因为 DrRacket,它给我感觉非常迟钝,不过我确实认为 DrRacket 是对 IDE 能做什么的一种很酷的另类思路。比如当你把鼠标悬停在一个变量上时,它会显示一条线指向该变量的来源。 CHICKEN 是一个实用且快速的系统,社区不错,许可证也可以接受(我当时对 GPL 相当反感)。CHICKEN 也是仅有的两个(据我们所知)采用 Cheney on the MTA 技术的实现之一,其原理在 [这里](https://wiki.call-cc.org/chicken-compilation-process) 有解释。它有很多粗糙之处,但我认为正是想要解决这些问题的念头,让我得以如此深入地钻研核心。如果一切都是完美的,那可就没什么事可做了! 所以我开始为 CHICKEN 做一些贡献,起初只是几个不起眼的 egg(CHICKEN 的包,[https://wiki.call-cc.org/eggs](https://wiki.call-cc.org/eggs)),最终深入到了核心系统。我对 Lisp 内部的了解基本都是靠实践学来的——折腾 CHICKEN 的核心,各种尝试。我读了 Queinnec 的《Lisp in Small Pieces》,它讲到向 C 的翻译,但*很多*内容都没讨论,而且充满了面向对象的东西,很分散注意力。SICP 有一些不错的材料。然后还有 Appel 的《Compiling with Continuations》,篇幅很短、直奔主题,却依然相当全面;我最喜欢这种书了。 总的来说,我就是喜欢折腾核心,即使如今能投入的时间并不多。我得强调一下,我学得比较慢。我对 CHICKEN 的理解是经过多年积累的过程,而且系统中仍有些部分我不是特别熟悉(不过我熟悉到足够在需要时快速上手)。 **那几本 Lisp 书缺了什么?** 《Compiling with Continuations》只用了很小的篇幅讲运行时系统,所以对垃圾回收和数据表示之类的讨论并不深入。据我所记,《Lisp in Small Pieces》没有讨论 continuation passing style。而且它的数据表示也不太优化。我喜欢在[博客](https://www.more-magic.net/archive.html)上写一些如今已经很少有人讨论的酷技术。比如实现[弱引用](https://www.more-magic.net/posts/weak-references.html)以及如何高效地回收它们。其他我很少看到有人讨论的内容还包括:FFI 的用法、跨模块优化、分离编译和交叉编译(只有极少数 Scheme 实现支持)等等。 **Scheme 对你来说意味着什么?** 总的来说,Scheme 对我而言是一种非常干净的语言,核心极小,便于实验。这也是标准化进程中的根本张力——生产级的 Scheme 往往会不断膨胀,而标准化这些是有价值的。但这也会消解掉让实验性实现成为可能的那种极简性。例如,Felix Winkelmann(@Bunny351,CHICKEN 的原作者,[他谈 Scheme 实现的视频](https://www.youtube.com/watch?v=VZp1wWivFYc))曾经开始做一个 Common Lisp(子集)的实现,在其中大量实验类型和流分析,最终催生了 CHICKEN 的类型相关功能。 **你对整个 Scheme 生态怎么看?R7RS、SRFI 与实现专属库的对比等等?有几个实现似乎已经不在乎这些了。** 我认为把 R7RS 拆分为 small 和 large 两个版本是正确的做法,因为 R6RS 既被极简主义者所痛恨,又被激进派认为不够用。总体上,我为 R7RS 感到有些遗憾——如果一些规模更大的社区 Scheme 实现基本上完全无视它,那我觉得它们做错了。很多、甚至可能是大多数 Scheme 实现本质上都是单人项目。我觉得 CHICKEN 似乎也在朝着这个方向发展,因为我们失去了不少贡献者(主要因为生活状况的变化),而且很难吸引到新的贡献者。 与此同时,R7RS "large" 项目有点走火入魔了,完全按自己的想法推进,不怎么关心社区的认可度。R7RS large 的变化速度也有点快,让人跟不上。他们在几年之内抛出了大量的 SRFI(实际上,现在回头看似乎也没有*那么多*,但肯定比过去 SRFI 的产出速度要快得多)。不管好坏,SRFI 流程向任何人开放提交。我注意到有几位新的贡献者为 CHICKEN 提交了一些较新 SRFI 的实现,这是好事,我很高兴至少有人愿意费这个心。 CHICKEN 6(https://www.more-magic.net/posts/chicken-6.html)基于 R7RS,但较旧的 CHICKEN 代码仍将继续工作。我们仍然支持旧的模块语法(那才是"原生"语法)。R7RS 的库声明本质上是核心模块语法的语法糖。R7RS-small 几乎完全向后兼容 R5RS,所以这里不存在冲突。将一个 egg 移植到 CHICKEN 6 通常只需要做几处小调整,因为一些(非 R5RS 的)标识符在模块之间被重新安排,以更好地符合 R7RS 风格。 **CHICKEN 的开发流程是怎样的?** CHICKEN 4 是"卫生化 CHICKEN",引入了模块系统(并需要彻底改造宏展开器)。这一切都是 Felix 一个人完成的,需要对宏如何与模块交互等有非常深入的内部知识。 CHICKEN 5 是一个彻头彻尾的社区协作成果。它主要是一个理顺和清理的版本,我们对模块(什么放在哪里)进行了一次大规模重组,使其更合乎逻辑、也更好地契合 R7RS。我们是在一次线下聚会(IRL meetup)上讨论这件事的,随后几个月里一直在推进。(社区是 CHICKEN 的一大优势!)我们还加入了[数值塔](https://www.more-magic.net/posts/numeric-tower-part-1.html)。 CHICKEN 6 基本上是从 Felix 的分支上切出来,以使 UTF-8 的处理变得合理且一致(有点像 Python 2 → 3 的迁移,但破坏性小得多)。字符串与字节向量(bytevector)之间有严格区分,端口和其他 I/O 也有相应改动。我们借此机会将 R7RS egg 集成到了核心中,使其更加"原生"。FFI 中的字符串应该会更高效,因为不再有无谓的复制了。 CHICKEN 6.0.0(https://code.call-cc.org/releases/6.0.0/NEWS)曾因一个导致堆损坏的 bug(https://lists.gnu.org/archive/html/chicken-hackers/2026-07/msg00008.html)而延期发布(一定要去看看那个补丁的描述!)。我们之前完全找错了方向。这些堆损坏看起来是随机出现的,但只发生在 CHICKEN wiki 服务器上,而普通 Web 服务器提供简单文件、甚至整个 [Awful](https://wiki.call-cc.org/eggref/5/awful) 框架都没有问题。我们强烈怀疑是 [Subversion 客户端库](https://wiki.call-cc.org/eggref/6/svn-client)(wiki 用它作为内容的后端存储)的问题,我们在其中也发现了其他问题(由于 libsvn 的设计,那段代码回调很多,有些难缠)。 wiki 是一个相当小的程序,Web 技术栈的其余部分似乎都没问题,所以我们怀疑是 svn 客户端库。但我把 wiki 的代码削减到几乎一无所有,它还是照样崩溃。当我注释掉 URI 规范化代码之后(打开 symlink 后面的页面时会发生重定向,以获得指向原始文件的规范 URL),它突然就不崩溃了! 那段规范化代码看起来似乎没做什么大事,所以我们很快定位到了 `read-symbolic-link`。对核心系统中的代码匆匆一看就确认了,它彻底坏掉了,而原因正是 CHICKEN 6 的 UTF-8 过渡期间所做的一个改动。 **6 发布之后,下一步是什么?** 关于 CHICKEN 的目标,有几件事我想做。我想到的一个点子是通过"前导代码"(prelude)来教会编译器识别不安全的内置操作(unsafe intrinsics)。由于 Scheme 是一门安全但动态类型的语言,内置操作会带来一些开销,比如对非 pair 调用 "car" 会抛出异常。如果编译器能推断出你传入的对象必定是一个 pair(也许是因为你之前用 `pair?` 检查过,或者之前对它调用过 `car` 或 `cdr`),就可以替换为不安全的、不做检查的版本。但目前这一切都非常临时性的(ad-hoc),而且用户无法扩展。我的想法是提供一个独立的定义,将不安全操作与"类型检查前导代码"分开,后者可以在调用点被内联展开。这样,当需要做多项检查时,就不必非此即彼。我们可以省略不必要的检查,只做必要的检查,而且这套机制也可能延伸到用户代码。 另一个想法与日期和时间的处理方式有关——核心中有一些访问 POSIX 函数的东西,但很乱,而且(在我看来)基本不可用。替代方案是 SRFI-19,它是个庞然大物,支持多种历法系统、本地化等等。也许可以在核心里放一些极简的东西(可能只支持英文),这样你就有了一个在各处通用的类型(在库之间共享对象时很方便,不必因此对 SRFI-19 引入一个很大的依赖)。然后你可以用它来解析常见协议中的时间戳之类的。 ### Postgres 与 SQLite **你最喜欢或最了解哪些领域?** - Web 相关:我维护 CHICKEN 的 HTTP 和 URI 实现 - CHICKEN 内部机制:GC、宏展开器和 Irregex 实现 - 性能优化:虽然不是专家,但我做过不少,而且一直乐在其中 - Postgres:虽然我没有深入研究过它的内部机制,但在我就职过的公司里,我通常是(Postgre)SQL 问题的首选咨询对象。有意思的是,我在大学时数据库/SQL 那门课差点不及格,完全没搞懂 SQL - 分布式系统:虽然我在工作中做了六年相关开发,但如果条件允许,你最好像躲瘟疫一样避开它。要理解整个大系统的行为非常困难,而且你没办法把它抽象掉 我在非常努力地思考有什么东西是让我真正兴奋的。目前我看到的最大积极信号是推动数字主权(digital sovereignty)的努力。我真诚地希望这能改变人们部署技术的方式,也许是以一种更审慎的方式。更多开源、更少依赖外国(也希望是整个大型科技公司)的产品。但既得利益和惯性将是难以克服的障碍,真让人心灰意冷。 **为什么选 Postgres?** 我真正学会数据库是在一家使用 Rails 的日历类创业公司。我们在数据库中实例化了重复出现的事件,而这些事件有时需要更新。起初,我们在循环中逐个获取模型并逐条更新,速度慢得让人痛苦。后来我们终于发现了批量更新(我记得*似乎*还必须直接调用数据库,因为当时 Rails 不提供这个功能)。这让我一下子开了窍——性能的重要性以及 SQL 的用处。当时 MySQL 仍然是 Rails 的默认选择,我为我们使用的一个 CMS 多次陷入 MySQL 字符集的地狱。后来,另一个 Rails 项目需要存储海量数据(计算流体力学模拟),MySQL 每次尝试批量导入都会直接崩溃。 研究替代方案时,我发现 Postgres 处理这些数据毫无问题。后来我又了解到 Postgres 没有 MySQL 那些愚蠢至极的缺陷。比如,UTF-8 字符在存储时会经过验证,所以你不会像在 MySQL 里那样轻易陷入字符集地狱;而且它实际上允许在事务中执行 DDL 语句,所以你可以获得原子性生效的事务性迁移。当时真是让我大开眼界。我彻底被说服了! Postgres 在几乎所有方面都更加规整、表现更可靠,而且没有奇怪的限制(例如在 MySQL 里,你甚至不能给长度不确定的 text 列加索引)。MySQL 允许你把空字符串存入任何非空 enum 列。这对我来说毫无道理!数据库里到处都是这种地雷。我该停止发牢骚了——一说到 MySQL 真让我火冒三丈。另外,我也越来越依赖一些"更高级"的功能,比如 LISTEN/NOTIFY、数组存储、窗口函数、CTE 等等。不过,我发现存储过程其实用起来不太好——"真正的代码"更加灵活,因为不需要那些麻烦的迁移来保持同步。 我不太喜欢在关系型数据库里用 JSON,但我也确实会在存储任意数据、或者真的把来自 API 等来源的 JSON 结果存进数据库时使用它。 我们在客户端通过 Cloju

相似文章

Lobsters对Claudius的访谈

Lobsters Hottest

对Claude Roux的访谈,他是LispE和TAMGU的维护者,讨论他在计算语言学、符号人工智能以及基于规则的自然语言处理系统的局限性方面的职业生涯。

Chicken Scheme 6.0 发布

Lobsters Hottest

CHICKEN Scheme 6.0 已发布,增加了完整的 R7RS small 语言支持、UTF-8 字符串、字节向量操作,以及各种模块重命名和 API 变更。

Lobsters 专访 mitchellh

Lobsters Hottest

对 Vagrant、Terraform 和 Ghostty 的创建者 Mitchell Hashimoto 的深度专访,探讨他对终端的热爱、使用 Zig 构建 Ghostty 的过程以及基于终端的应用程序的未来。