第 19 章
宪法的余烬
“它也可以被视为采用了M-表达式的中缀记法的一种Lisp方言。”
这句话出现在Python语言史的某个角落,通常被当作一则趣闻而非严肃的谱系学论断。吉多·范罗苏姆于1980年代后期开始研发Python,作为ABC语言的后继者。他当时没有试图制造一种Lisp方言——这是有意还是无意,已无从确考。但M-表达式的幽灵确实在中缀记法里活了下来:John McCarthy在1960年发表的Lisp论文中提出这种替代语法方案,用中缀记法替代括号嵌套,让Lisp看起来更像当时的数学公式。它在Lisp社区内部从未真正流行过,但像一粒种子落进了不同的土壤。
三十年后,一个荷兰程序员在设计新语言时,无意中让这粒种子发了芽——不是通过继承Lisp的正统,而是通过继承一个被正统遗忘的可能性。这种传播模式——匿名的、断裂的、不被称为传承的传承——正是本书此前各章反复描摹的东西。
我们已经看到Clojure社区如何通过邮件列表、会议圆环、补丁审查、命名惯例、文档实践、测试文化、资助机制和REPL手艺,将一种编程范式沉淀为一套可以传递的共识。我们也看到这套共识如何越过Clojure自身的生态边界,渗进React的组件模型、Java 8的Stream API、Python数据科学的不可变数据结构,以及无数开发者对纯函数和副作用隔离的本能偏好。在上一章结尾,我们停在了一个问题上:这种遗产因其匿名性和传播断裂而无法被精确追溯——这种未被命名的传承,其意义最终能否被确认?
把时间拨回2024年。Clojure邮件列表上出现了一个讨论帖,主题是一个被广泛使用的核心库是否应当引入破坏性变更。发帖人的措辞小心翼翼,先花三段话解释自己理解变更的代价,再用两段话说明为什么他认为代价可能是值得的,最后以一个问句结束,询问社区的看法。
接下来的回复呈现出一种几乎可以称为仪式化的节奏。第一封回复间隔了大约四个小时,回复者没有直接表态,而是提出了一个技术上的边界情况。第二封回复来自另一个时区,语气同样谨慎,补充了另一个需要考虑的维度:那些依赖这个库但已不再活跃维护的下游项目会怎样。直到第五封回复,才有人开始小心翼翼地表达倾向性意见,而且这个意见被包装在大量限定条件中——确保迁移工具足够可靠,给出足够长的过渡期,在文档中明确标记变更的边界。
阅读这些邮件,几乎可以听到2008年的回声。2008年,Clojure的第一个邮件列表刚刚建立,那时的讨论也是这样的节奏:没人在第一时间表态,每个人都倾向于先列举边界条件,技术论证总是与对社区影响的考量交织在一起。那些邮件存档至今仍可查阅。它们记录了一种独特的讨论文化的诞生——不是通过任何人的设计或规定,而是通过最初几十个参与者不约而同的选择。他们选择了这种缓慢的、试探性的、充满限定词的说话方式,不是因为他们缺乏确信,而是因为他们意识到自己正在参与塑造某种比任何个人观点都更长久的东西。
十六年过去了。最初的那些参与者中,有些人已经离开,有些人减少了参与频率,有些人角色发生了变化。核心团队成员在更替。资助模式经历了从个人掏腰包到Clojurists Together的制度化转型。但当那个关于破坏性变更的讨论在2024年展开时,它的措辞、节奏与论证方式,与2008年第一封邮件中的语气惊人地相似——同样的小心翼翼,同样的对社区共识的反复试探,同样的在技术理由与人文考量之间的缓慢摇摆。
这是怎么发生的?没有人写过一份Clojure社区讨论指南。没有任何文档规定了邮件列表上的回复节奏或措辞风格。但这种风格被传递了下来。它的传递媒介不是文字,而是实践本身——新来者阅读邮件列表存档时,吸收的不只是技术问题的答案,还有提出问题和表达异议的方式。当他们第一次鼓起勇气回复一封邮件时,会不自觉地模仿他们读到过的那些回复的语气和结构。这种模仿不是刻意的,它更像是学习一种语言的口音:听得多了、说得多了,自然就带上了那种腔调。
这就是共识仪式最深层的工作方式。它不是通过规则传递规则,而是通过示范传递习惯。这种传递机制的优势在于低摩擦:不需要强制执行,不需要惩罚违规者,甚至不需要明确表述规则本身。但它的脆弱性也同样明显:一旦示范链断裂,一旦足够多的人不再以那种方式行动,整个习惯体系就可能在一个世代内消失。
要回答这个问题,我们需要先理解另一种可能性。2008年12月,Python 3.0发布了。这是Python社区历史上最具争议的决定之一:对语言做较大修订而不能完全后向兼容。尽管提供了2to3自动转换工具,仍有大量现存代码不能移植。2.7版的产品寿命结束被一再延期,最终定在2020年元旦——距离3.0发布整整十二年。在这十二年间,Python社区经历了分裂、争论、缓慢的迁移和代际更替。今天回顾这段历史,大多数观察者会同意Python 3的决定是正确的——它清理了语言中积累多年的设计债务,为后来的增长奠定了基础。但代价也是真实的:一个社区被分成两半长达十年,大量精力消耗在迁移而非创新上,一些库和项目在这个过程中被遗弃。
Python的做法代表了一种共识达成模式:由一个被赋予决策权的核心人物或团队做出决定,然后整个社区被要求跟随。这种模式效率很高——决策迅速,方向清晰,执行有力。但代价是共识的表面化:那些不同意决定的人要么离开,要么在沉默中不满,要么在漫长的过渡期中缓慢消化这个决定的冲击。
Clojure社区选择了另一条路。这并不是说Clojure没有经历过关于破坏性变更的争议。仔细翻阅邮件列表存档、JIRA工单和会议记录,可以发现至少三次重大的争议事件,每一次都涉及核心语言特性或关键库的变更方向。但Clojure社区处理这些争议的方式,与Python社区形成了鲜明对比。
第一次重大争议发生在2010年前后,涉及一个核心数据结构的实现细节是否应该调整。双方都有充分的技术理由:一方认为调整可以显著提升性能,另一方认为调整会破坏某些边缘情况下的行为一致性。在许多开源项目中,这种争议最终会由项目创始人或核心团队做出裁决。但在Clojure的案例中,讨论持续了数周,最终达成的不是一项裁决,而是一种区分:核心数据结构保持稳定,但新的性能优化作为可选变体被引入,让使用者自行选择。决定以这样一种方式呈现,就好像它是从讨论本身自然生长出来的——不是某个人强加的结果,而是讨论的内在逻辑引导参与者走到了这里。
第二次重大争议发生在2014年左右,涉及一个被广泛使用的宏的语义是否应该修改以消除一个已知的陷阱。讨论更加激烈,因为涉及的不只是技术问题,还有教学问题:那个陷阱已经坑过无数新手,修改它似乎是一种对后来者的责任。但也有人指出,修改会破坏大量现有代码,而这些代码的作者中有许多已不再活跃,无法为自己的代码辩护。讨论最终没有产生一个“决定”。
取而代之的是,社区发展出了一种双重实践:核心库保持不变,但文档和教程开始以一种特定的方式教授这个宏的使用——强调其陷阱,提供绕过的模式,并在示例代码中展示这些模式。共识不是通过改变代码达成的,而是通过改变围绕代码的知识传递方式达成的。
第三次重大争议发生在2018年,涉及一个构建工具的设计方向。双方在技术哲学上存在根本分歧:一方认为工具应该提供更多约定和默认配置以降低新手门槛,另一方认为工具应该保持最小化和可组合以尊重有经验开发者的判断力。这个争议从未被正式解决。它最终以一种非正式的分工沉淀下来:核心工具保持最小化,但社区成员创建了一系列补充工具和模板,为偏好更多约定的开发者提供替代路径。这种解决方式的精妙之处在于,它没有强迫任何一方放弃立场,而是允许两种实践在同一生态中共存。
回顾这三次争议,一个模式浮现出来:Clojure社区从未试图通过一次性的权威裁决来“解决”争议。相反,它在每一次争议中都发明了一种新的共存方式——有时是技术上的区分,有时是知识传递方式上的调整,有时是生态位上的分工。这些解决方式不是预先设计好的,而是在讨论过程中被逐步发现的。它们之所以能被发现,正是因为社区没有急于达成结论,而是允许讨论以那种缓慢的、试探性的、充满限定词的节奏展开。
这让我们回到2024年的那场讨论。最终的安排采取了这样一种形式:变更被接受了,但经过精心调制。变更本身被分解为多个较小步骤,每一步都提供明确的迁移路径。旧有功能没有被移除,而是被标记为不推荐使用,并附带指向新方式的文档链接。下游项目获得了足够长的过渡窗口,以及一系列帮助迁移的工具和指南。
但如果将它与2008年的第一封邮件、2010年、2014年、2018年的三次争议放在一起看,就会看到一条连续的线索:一个社区在不断学习如何达成共识,而不将共识固化为法典。每一次争议都是一次重新演练——不是在演练如何遵循规则,而是在演练如何在规则不存在或不再适用的情况下仍然共同前进。
这就是“隐性宪法”的真正含义。成文宪法有一个致命的弱点:一旦写下,它就与写下它的那个时刻绑定在一起。它可以被修订,但修订本身就是一项沉重的工程。它可以被解释,但解释需要权威机构,而权威机构本身的存在就改变了权力的分布。成文宪法在提供确定性的同时,也制造了僵化——它保护了某些共识不被轻易推翻,但也使共识的演化变得困难。
Clojure社区的隐性宪法走的是另一条路。它的约束力不来自文字,而来自预期——社区成员对违反某种实践会发生什么的集体预期。如果你在邮件列表上以一种咄咄逼人的方式提出意见,你不会被封号,但你会发现其他人以沉默回应你,你的意见不会被认真对待,你在后续讨论中的影响力会下降。如果你维护的库突然引入了破坏性变更而没有提供迁移路径,你的库不会从Clojars上被移除,但使用者会默默转向替代品,你的声誉会受损。这些后果不是任何人施加的惩罚,它们是从社区的集体行为中自然涌现的。
这种约束机制的有效性依赖于一个前提:足够多的社区成员共享同样的预期,并以同样的方式回应违反预期的行为。如果这个前提不再成立——如果足够多的新成员不再以那种小心翼翼的方式讨论,不再在被沉默对待时反思自己的方式,不再在遇到破坏性变更时默默转向替代品——那么这套隐性宪法的约束力就会消解。它不是被推翻的,而是被遗忘的。
这正是全书最终必须面对的问题:这种遗忘是否正在发生?或者更准确地说,这种遗忘是否不可避免?
在准备本章的过程中,我反复阅读了2008年到2024年间的邮件列表存档。这不是一项系统性的内容分析,而是一种更接近田野调查的阅读——试图感受讨论的语气、节奏和未言明的规则在不同年份之间的变化。我的印象是矛盾的。
一方面,那种小心翼翼、充满限定词的讨论风格确实在延续。即使在2024年的邮件列表中,新加入的开发者在第一次发言时仍采用与2008年参与者相似的措辞策略。这表明示范链尚未断裂——新来者仍然在通过阅读存档和观察讨论来学习在这里应该如何说话。
另一方面,一些微妙的变化也在发生。讨论的速度变快了——2024年的回复间隔通常以小时计,而2008年通常以天计。这不是因为人们变得更急躁,而是因为参与者的数量和时区分布发生了变化,也因为其他沟通渠道分流了一部分讨论,留给邮件列表的更多是需要慎重对待的话题。但速度的变化本身就在改变讨论的质地:当回复来得更快时,思考的时间更少,限定词可能会减少,边界条件的列举可能会不完整,试探性的语气可能会被更直接的表态所替代。
更重要的是,那些承载着社区记忆的人正在老去——这里的“老去”指的是他们在社区中的时间深度。当2008年的第一批参与者离开时,他们带走的不仅是技术知识,还有那种无法被文档化的默会知识——那种知道在这个社区中事情是如何做的直觉。新加入的成员可以阅读存档,可以学习规则,但他们无法通过存档体验到那些规则最初是如何在具体争议中被摸索出来的。他们继承的是结果,不是过程。
这就引出了一个更深层的问题:当共识仪式失去了它的创始记忆时,它是否会退化为形式主义?形式主义指的是一种特定的退化模式:实践的外在形式被保留下来,但其内在逻辑被遗忘。人们继续以小心翼翼的方式发言,不是因为理解这种风格背后的考量——给予不同意见充分空间、保护少数派的发言权利、让技术决策在充分的信息暴露后自然浮现——而是因为这是在这里做事的方式。限定词变成了礼貌的装饰,而不是认知谨慎的表达。边界条件的列举变成了展示技术能力的表演,而不是真正试图穷尽变更可能带来的影响。
如果这种退化发生,隐性宪法就变成了一种空洞的礼仪。它仍然存在,仍然被遵守,但已不再发挥最初的功能——将技术争议转化为可积累的治理惯例。那时的邮件列表讨论将不再是共识达成的场所,而是一种社交仪式,人们在其中表演共识,而不是创造共识。这不是预测,而是一种可能性——一种Clojure社区正在面对但尚未回答的可能性。
要理解这种可能性的分量,我们需要回到本书反复出现的一个主题:不可变性。Clojure的核心技术直觉是,不可变数据结构比可变数据结构更容易推理、更安全、更适合构建复杂系统。这个直觉被凝结在语言设计中,传递到库生态中,解释给每一个学习Clojure的新手。但它也是一个更广泛的文化隐喻:有些东西之所以能够持久,恰恰因为它们不可改变。
但共识不是不可变的。这正是全书最终要抵达的那个反讽:一个以“不可变”为核心隐喻的社区,它的治理机制却是彻底可变的——不仅可变,而且必须不断变化才能维持自身。每一次邮件列表讨论都是对共识的一次重新协商,每一次会议圆环都是对隐性宪法的一次重新演练,每一次补丁审查都是对社区边界的一次重新划定。共识没有被写入任何文档,因为它一旦被写入,就会失去那种需要被不断重新激活的生命力。
这听起来像是一个悖论,但它实际上描述了一种非常古老的治理智慧。在成文宪法出现之前,人类社会的规范就是通过这种方式维持的——不是通过文字固定下来,而是通过反复的实践、讲述和争议不断重新生成。这种方式的优势在于适应性:规范可以随环境变化而调整,不需要经过正式的修订程序。代价在于脆弱性:一旦实践的连续性被打断,规范就可能失传。
Clojure社区在过去十六年间所做的,本质上是在现代技术社区的条件下重建这种古老的治理方式。它之所以可能,是因为社区规模足够小——小到邮件列表上的每一个声音都可以被听到,小到核心团队成员可以亲自参与大多数重要讨论,小到示范链可以在日常互动中被自然地传递。它之所以必要,是因为社区没有大厂背书——没有一家公司可以像Google对Go语言或Facebook对React那样,为语言的方向提供制度化的决策机制和资源保障。
没有大厂背书,这曾经是Clojure被质疑最多的地方。在早期,批评者认为这意味着语言缺乏长期维护的保障。在中期,观察者认为这意味着生态无法达到临界质量。在今天,这些质疑大多已被事实回应:Clojure已经活过了十五年,生态虽然不大但足够健康,维护者虽然不多但足够稳定。但“没有大厂背书”的后果比这些质疑者所预想的要深刻得多:它意味着Clojure社区必须发明一种不同于大厂模式的治理方式。
大厂模式的核心是所有权和责任的集中化。Google拥有Go语言,因此可以决定其方向,也承担维护责任。这种模式的效率很高——决策迅速,资源充足,方向明确。但代价是社区参与的浅层化:使用者是消费者而不是共同所有者,可以提意见但不能做决定,可以贡献但不能治理。Clojure的模式正好相反。没有人拥有Clojure——Rich Hickey是最接近这个角色的人,但他刻意将自己定位为最终裁定者而非所有者,而且近年来他越来越多地将决策权分散给核心团队和社区讨论。也没有一家公司承担维护责任——Clojurists Together由社区成员资助,Cognitect提供重要支持但不是唯一支柱。这种分散化的结构迫使社区发展出一套分散化的治理机制。
这就是隐性宪法的制度根源。它不是一个哲学选择,而是一个生存策略。Clojure社区发展出那套规则,是因为没有单一个体或实体有足够的权威来强制执行一个决定。当没有人可以单方面宣布一个方向时,唯一的替代方案就是让方向从集体的缓慢协商中浮现出来。
这解释了一个看似矛盾的现象:Clojure社区在面对破坏性变更时表现出的极度谨慎,不是因为它有强规则禁止破坏性变更,而是因为它没有一个强中心来强制执行破坏性变更并承担其代价。Python可以做出Python 3的决定,因为Guido van Rossum和Python软件基金会有足够的权威说服社区跟随,也有足够的资源支持漫长的迁移期。Clojure没有这种权威和资源,因此它必须找到另一条路:让变更足够小、足够渐进、足够可逆,以至于不需要一个强中心来强制执行。
这不是更好的或更坏的方式,而是一个不同的方式。它的优势在于更尊重社区中每一个参与者的判断力和处境。它的劣势在于速度更慢,方向更模糊,存续更依赖一种难以言传的讨论文化的代际传递。
Clojure做出了与Python类似的选择——语言核心保持稳定,创新发生在库层面。但这个选择的后果在Clojure这里走得更远。因为Clojure没有一个像Python软件基金会那样的中央机构来管理生态,库层面的创新自由同时也意味着库层面的治理分散化。每一个库的作者都在自己的领域内扮演着类似语言设计者的角色:决定API方向、管理破坏性变更的节奏、回应使用者需求。当这些库作者之间需要协调时,他们不能诉诸更高权威来裁断,只能彼此协商。
这就将共识机制从语言层面扩散到了生态层面。那种小心翼翼的讨论风格,不仅出现在语言核心的讨论中,也出现在库作者之间的协调中、库作者与使用者之间的互动中。整个生态变成了一个巨大的共识演练场——不是在一个中央广场上进行的演练,而是在无数分散的角落中同时进行的演练,每一个角落都在以自己的方式重新发明和确认那套未成文的规则。
这或许是Clojure社区在过去十六年间最不为人知但最重要的成就:它证明了在没有中央权威的情况下,一个技术社区可以通过分散化的共识演练来维持自身的一致性和连续性。这个证明的意义远远超出了Clojure本身。在一个开源软件日益被大公司主导的时代,在一个技术治理日益集中化的时代,Clojure提供了一个反例——不是反例证明集中化是错的,而是反例证明另一条路是可能的。
但这条路的可持续性仍然是一个悬而未决的问题。当核心团队的成员逐渐老去,谁将接替他们?接替者将如何获得那种无法通过文档传递的默会知识?当资助模式面临新的经济压力,Clojurists Together的会员增长是否能跟上维护者生活成本的增长?当技术潮流再次转向,如果下一个主流范式不是函数式编程而是某种尚未命名的东西,那些因函数式编程而聚集的人是否会散去?
这些问题没有答案,因为答案取决于未来尚未做出的选择。本书不能预测这些选择,但它可以指出这些选择将在什么样的结构约束下被做出。那些约束就是隐性宪法本身——不是作为一套固定的规则,而是作为一种已经被反复演练了十六年的实践习惯。
当未来的争议出现时,Clojure社区的成员将带着这些习惯进入讨论。他们可能意识到这些习惯的存在,也可能不意识到。他们可能有意识地遵循这些习惯,也可能在无意中偏离它们。但无论如何,这些习惯将塑造他们可用的选项范围——不是通过禁止某些选项,而是通过使某些选项在讨论中显得自然、合理、值得考虑,而使另一些选项显得突兀、草率、需要更多的论证负担。这就是传统的工作方式。它不是一条锁链,而是一种重力——你可以对抗它,但对抗需要额外的能量;你可以忽视它,但忽视会在你周围制造摩擦;你可以改变它,但改变需要时间、耐心和足够多的人在不同的角落做出相同的微小调整。
Clojure社区的传统是关于如何达成共识的传统。这不是一种关于什么是对的的传统——尽管它也包含技术判断——而是一种关于如何共同寻找什么是对的的传统。这种传统的内容不是结论,而是过程。它的遗产不是答案,而是提问的方式。
从这个角度看,“宪法的余烬”这个标题有了另一层含义。余烬不是灰烬——灰烬是已经燃尽的东西,余烬是仍然在燃烧的东西,只是燃烧的方式从明火变成了暗火。明火耀眼但消耗得快,暗火不显眼但持久。Clojure社区的隐性宪法从来不是明火——它从未以宣言、宪章或正式治理文件的形式燃烧过。它一直是一种暗火,在邮件列表的缓慢讨论中燃烧,在会议圆环的非正式交流中燃烧,在补丁审查的细致协商中燃烧,在库命名的不成文规则中燃烧,在文档实践的反复摸索中燃烧。
这种暗火的持久性来自它的分散性。明火集中在一处,一旦燃料耗尽或被风吹灭就结束了。暗火分散在无数个微小的燃烧点中——每一个实践着那种讨论风格的人都是一个燃烧点,每一个在代码评审中遵循那种节奏的团队都是一个燃烧点,每一个在写文档时采用那种克制语调的作者都是一个燃烧点。只要还有足够多的燃烧点在燃烧,暗火就不会熄灭。
但这同时也意味着,暗火的熄灭不会有明确的时刻。不会有那样一天,Clojure社区宣布“我们的共识机制失效了”。相反,它会在不知不觉中发生:讨论变得越来越快,限定词越来越少,边界条件不再被完整列举,破坏性变更不再引发那种小心翼翼的漫长协商,新来者不再通过阅读存档学习讨论的风格,示范链在一个又一个环节上悄然断裂。等到有人注意到时,那种曾定义了这个社区的讨论文化已经变成了档安中的遗迹——仍然可以查阅,但不再被活人实践。
这是否正在发生?本书无法给出确定的答案。十六年的时间对于一个技术社区来说已经很长,但对于一种文化传统的生命周期来说仍然太短,不足以做出结论性的判断。我们所能说的是:到目前为止,那些燃烧点还在燃烧。2024年的那场关于破坏性变更的讨论证明了这一点——它的措辞、节奏与论证方式,与2008年第一封邮件中的语气惊人的相似。这不是因为有人在强制执行相似性,而是因为那种风格还在被自然地传递着。
但传递本身就是一种脆弱的奇迹。每一次传递都是一次微小的变形——接收者永远不可能完美地复制发送者的习惯,总会有一些东西在传递中流失,另一些东西在传递中加入。经过足够多次传递后,累积的变化可能大到使最初的习惯面目全非。这是所有传统的命运:要么因僵化而死亡,要么因变形而改变到不再能被识别为同一种东西。
Clojure社区的隐性宪法将在哪一个方向上找到自己的命运?它会因为过度固化而变成一种空洞的形式主义——那种小心翼翼的语气变成一种社交礼仪,失去最初的认知功能?还是会因为过度变形而消散——随着新成员的加入和新平台的兴起,那种缓慢协商的习惯被更快速、更直接的决策方式所取代?
也许这两种命运都不是必然的。也许存在第三条路:传统不是被保存或丢弃的物件,而是被不断重新发明的实践。每一次重新发明都会引入变化,但这些变化不一定是指向消散的——它们也可以是指向更新的。Scheme在Lisp方言中最早采用了词法作用域和尾调用优化,使函数式编程的影响扩展到更广的范围。它没有试图保存Lisp的所有传统——它抛弃了动态作用域,引入了尾调用优化,简化了宏系统。这些变化在当时被一些Lisp程序员视为背叛。但从更长的时间尺度来看,Scheme恰恰是让Lisp的核心思想得以在更广泛的编程世界中存活下去的那个变形。通过改变形式,它保存了本质。
Clojure本身也可以被视为Lisp传统的又一次变形。它抛弃了Common Lisp的面向对象系统,选择了不可变数据结构作为默认;它运行在JVM上而不是Lisp机器上;它的语法在某些方面比传统Lisp更简洁,在另一些方面更严格。这些变化同样在当时被一些Lisp程序员视为背叛。但从现在的位置回望,Clojure所做的是将Lisp的函数式编程直觉翻译成了一种能让21世纪的开发者理解和使用的方式。
那么,Clojure社区正在经历的变形是什么?也许是从一个围绕单一语言组织的社区,变形为一个围绕某种编程实践方式组织的松散网络。这种实践方式包括REPL驱动开发、不可变数据建模、函数式组合、对副作用的自觉隔离、以及那种小心翼翼的共识达成过程。这些东西不一定非要绑定在Clojure这门语言上才能存活——它们已经通过React的组件模型、通过Immutabe.js、通过Redux的状态管理、通过Java 8的Strea API、通过Python数据科学社区对不可变数据结构的拥抱,扩散到了更广泛的编程世界中。这就是本书在上一章中追踪的那个过程:括号之外的遗产。
当不可变性与函数式组合已成为主流常识时,Clojure社区在括号之外留下的遗产因其匿名性和传播断裂而无法被精确追溯。这种未被命名的传承,其意义最终能否被确认?也许这个问题本身的提出方式就需要被修正。确认遗产的意义,不一定是为它命名或追溯其谱系。意义也可以以一种匿名的、不被确认的方式存在——就像M-表达式的幽灵在中缀记法中存活了下来,尽管大多数使用中缀记法的程序员从未听说过M-表达式;就像词法作用域在现代编程语言中成为默认,尽管大多数使用这些语言的程序员从未阅读过Scheme的λ论文集;就像不可变数据结构在前端开发中成为流行实践,尽管大多数React开发者从未写过一行Clojure代码。
传播不需要命名。影响不需要被承认。遗产不需要被确认为遗产才能发挥作用。那些从Clojure社区扩散出去的实践和直觉,已经在它们所抵达的每一个角落按照自己的逻辑生长。它们不再是Clojure的一部分,它们变成了它们自己。这种匿名性不是遗产的失败,而是遗产的成功——它意味着这些实践和直觉已经变得如此自然,以至于人们不再觉得需要追溯它们的来源。
这或许就是Clojure留给更广泛的开源世界的最安静、也最持久的遗产:不是一门语言,不是一套库,不是一种方法论,而是一种可能性——一群人在没有大厂背书、没有中央权威、没有成文宪法的情况下,通过反复的共识演练维持了一个技术社区十六年并且仍在继续的可能性。这种可能性不需要被命名才能存在。但它需要被记住才能被重复。
这就是本书试图做的事情:不是为Clojure社区立传,不是为隐性宪法编撰文本,不是在余烬冷却之前抢救灰烬中的文字。而是记录一种实践方式曾经存在过,曾经运作过,曾经让一群人能够在技术变迁的洪流中持续地选择以特定的方式共同存在。这种记录本身也是一种传递——不是传递规则,而是传递记忆;不是传递答案,而是传递提问的方式。
共识从未完成。它只是被不断地重新开始。每一次邮件列表上的小心翼翼的发帖,每一次会议圆环中的试探性提议,每一次补丁审查中的边界条件列举,都是一次重新开始。这些重新开始加在一起,构成了一个社区的生命。这个生命没有终点线,没有最终版本,没有可以刻在石牌上的完成形态。它只有持续的练习——就像REPL中的手艺人不断地试验、修改、重试,不是在追求一个最终的正确答案,而是在追求一种越来越熟练的与问题共处的方式。
这是不可变的共识中那个最深的悖论:唯一不可变的东西,是共识必须不断变化这一事实本身。