[AI翻译]来自Zig的教训
来源网址:http://www.vinniefalco.com/p/lessons-from-zig
发布时间:2026-02-07T07:40:15+00:00
Zig 编程语言保持了一个故意精简的标准库。那些不符合严格纳入标准的组件会被移除,并转移到社区维护的包中。这种哲学得益于一流的包管理器,它让第三方代码变得轻松可得。
C++ 没有这样的逃逸阀。每一个添加到标准库的组件都会产生永久性的义务:编译器厂商必须永远维护它,所有未来的提案必须分析它的交互,每个教育者必须教授它(或者教学生避免使用它)。添加的成本是有限的,但维护的成本是无限的。
本文主张 WG21 应该采纳类似于 Zig 的标准库哲学,关于哪些内容应纳入标准库。这个主张纯粹是经济性的:委员会的稀缺资源应当分配给那些其协调效益超过永久维护成本的组件,而证明这一点的标准应该明确、高标准并且一致执行。
Zig 语言由 Andrew Kelley 创造,它对标准库的范围持有一种谨慎的立场。标准库专注于低级、基本的工具:内存分配器、数据结构、字符串操作以及跨平台的操作系统抽象。特定领域的功能则被明确排除在外。
社区讨论已经清晰地形成了这一立场:
• 内存操作属于标准库。 分配器、队列、字符串和基本数据结构几乎服务于每一个程序。
• 文件格式处理不属于标准库。 Tar、zip、JPEG 等格式被认为过于专用,每一种都是“自己的庞大项目”,更适合由专门的库来处理。
• 高级框架不属于标准库。 例如,HTTP 客户端被认为不适合成为一个通用系统语言的标准库一部分。
Zig 不仅仅避免添加新组件,它还主动移除它们。std-lib-orphanage 仓库(已于 2025 年 11 月归档)包含了从标准库中移除的代码,并且以 MIT 许可开放,允许社区维护。例子包括:
• realpath() 被移除,因为它不可移植,依赖于旧的权限模型,并且“通常调用它是一个 bug”。
• 红黑树实现被转移到社区拥有。
• 文件系统 API 已经从 std.fs 重组到 std.Io,以更好地反映它们的正确范围。
这种缩减标准库的态度非常引人注目。在大多数编程语言社区中,添加的内容是永久性的。而 Zig 将标准库视为一个策划过的集合,当某些组件无法证明其维护负担时,应当缩减它。
Zig 的简约主义之所以可行,是因为该语言配备了一个一流的包管理器。第三方依赖轻松可得。当某个组件离开标准库时,用户并不会被抛下。他们只需添加一个依赖,继续工作。
这是关键的推动力。没有易于获取替代方案的简化标准库会带来惩罚。通过包管理器,简化反而成了一种优势:标准库保持专注,生态系统吸纳其余部分。
C++ 标准化的经济结构展现出一种根本的不对称性。提案的作者在几年的时间里投入有限的精力,但一旦被接受,这个成本就终止了。
然而,标准必须终身考虑这些添加:
• 每一个后续提案必须分析与新组件的交互。
• 每一个核心语言的演变(如概念、反射、契约)必须考虑其对现有库的影响。
• 每一个相邻领域的缺陷报告都可能牵连它。
• 每一个编译器厂商必须永远实现并维护它。
• 每一个 ABI 问题将永久约束未来的演化。
• 每个教育者都必须决定是否教授它。
• 每个新的 C++ 程序员都必须学习它或学会避免它。
标准的组合复杂性单调增长,这种复杂性税负将不断增加,贯穿所有未来委员会的工作。提案者支付一次成本,但所有其他人要承担其余的成本。
这种不对称性造成了经典的经济外部性。提案者捕捉了标准化的集中好处(如声望、设计的规范地位),而分散、永久的维护成本则被社会化,分摊到所有未来的委员会成员身上,其中大多数人没有参与原始决策。
合理的激励机制是积极提出并不加批判地捍卫新增内容,因为提案者几乎不承担他们所施加的长期成本。如果没有机制迫使提案者承担这些永久成本,标准库就会无限扩展。
C++ 标准库已经包含了许多警示性的例子:
• std::regex:推出时慢,无法修复因为 ABI 约束,且许多专家建议不要在性能关键的代码中使用它。
• std::any:一个没有人需要的词汇类型;使用率低,牺牲了类型安全,常被视为标准化的遗憾。
• std::auto_ptr 和 std::rel_ops:从发现缺陷到移除花费了超过十五年。
• std::codecvt面:已被弃用,仍然在维护。
• std::filesystem:在 2003 年定型的编码假设在 Windows 上产生乱码;vcpkg “彻底移除了对 std::filesystem 的使用”。
每一个在提案时看似合理的组件,如今都带来了持续的成本,但几乎没有相应的好处。委员会缺乏任何正式机制来审计标准化特性是否兑现了它们承诺的价值。
Samo Burja 的“大创始人理论”观察到,功能性机构是例外,而不是常态。随着知识的流失,功能性机构的衰退不可避免,特别是知识的传递受到不完美的影响。每一代人都在基于“复印件的复印件”工作,没有了创造性原理,传统就无法恢复已失去的东西。
这一模式直接适用于标准库组件。设计的理由、考虑过的权衡和被拒绝的选择、为何选择特定 API 形态的理解——这些知识存在于创始人头脑中,并且当他们退出或去世时,这些知识会消失。委员会现在必须通过规范文本倒推意图。
每一个添加到标准中的组件都会形成一个新的知识传统,需要维护。一个更小的标准库意味着更少的传统需要维护,较少的继承危机,也减少了未来委员会成员要应对的复杂性。
GFT 指出非功能性机构的一个模式:机构的主体优化外观而非功能。在 WG21 的背景下,这表现为对添加组件的偏见(可见的、可衡量的进展),而不是对维护、改进或移除现有组件的艰难工作。
没有委员会成员会因移除 std::codecvt 而建立事业。事业是建立在增加提案上的。这种不对称的激励推动着扩展,不考虑扩展是否真的为用户服务。
Zig 愿意主动从标准库中移除组件,展示了一种根本不同的制度姿态:将收缩视为合法的进步。这需要 GFT 所称的“活跃玩家”——一个拥有决策权和远见的人,能够做出那些官僚程序反感的决定。
Zig 的纳入标准库的标准是隐式的,但很明确:一个组件只有在它提供低级、基本的功能,且几乎每个程序都需要时,才应当纳入标准库。C++ 应该将这一标准明确化。
一个库组件应当在符合以下两个条件时才被标准化:
• 稳定性信心:设计已经经过多年的生产使用,并且没有要求重大接口变更。已知的缺陷已被解决,而不是被推迟。
• 词汇必要性:独立的库生态系统显著要求类型一致性才能互操作。有证据表明,协调失败无法通过第三方分发解决,标准化可以解决这些失败。
“这会有用”是必要的,但不够充分。有效的库可以在标准之外茁壮成长。问题是:为什么这种有用性_需要_标准化而不是通过第三方分发?
Zig 的哲学之所以有效,是因为包管理器让外部库成为一流公民。C++ 缺少这个,这就造成了将所有内容都放入标准库的压力。但答案不是屈服于这种压力,而是要投资于生态系统。
委员会的带宽有限且宝贵。每一会议小时数花费在一个小众库组件上,就意味着这一小时不能用于以下工作:
• 对所有人有益的核心语言改进。
• 解决真正的协调失败的词汇类型。
• 使外部库更易访问的生态系统基础设施。
库扩展的机会成本表现为推迟了委员会唯一能够做的工作。外部库可以由任何人维护,而语言演进和词汇协调则需要委员会来处理。
C++ 标准历来认为移除几乎是不可能的。弃用可能需要十年时间,而实际移除则需要更长时间。这种单向拉紧的机制确保了标准库的无限增长。
Zig 展示了另一种方式:当某个组件不再能证明其位置时,迁移它。代码并不会消失,而是移到另一个地方,可以在不对核心产生负担的情况下发展。
C++ 无法完全复制 Zig 的方法——ABI 稳定性和几十年的部署代码使得移除变得复杂得多。但委员会可以采纳这一 心态:添加应当被视为暂时的,而非永久性的。每个组件都应该定期证明它继续存在的合理性。如果某个设施存在已知缺陷且无法修复,诚实地承认这一点,比维护虚伪的假象要更有益于用户。
这个论点是循环的。标准库之所以增长,是因为生态系统缺乏良好的依赖管理。生态系统停滞不前,因为所有重要的东西都期待在标准库中。打破这个循环需要选择一个方向。Zig 选择了投资生态系统。C++ 应该考虑同样的做法。
另一种选择——继续扩展标准库,作为生态系统基础设施的替代方案——会带来可预测的后果。标准库变成了一个 ABI 冻结的设计仓库,反映了它们在标准化时所做的假设。以性能为导向的组织放弃 std::,选择内部替代品。标准库最终成为了它原本不该是的样子:在 API 边界使用,内部避免。
标准库提供规范,而非质量。std::regex 被规范化且速度慢。std::filesystem 被规范化且存在编码问题。规范保证了接口的可移植性,而不保证实现的正确性或适应性。
外部库可以提供它们自己的保证:测试套件、基准测试、部署证据、响应式维护。这些通常对用户来说,比 ISO 文档编号更有意义。
初学者从一个 连贯 的标准库中获益多于从一个 庞大 的库中获益。一个小而有效的库比一个庞大且需要专家知识才能导航的库更易于教授。“使用 std::regex 但不适合性能”以及“使用 std::filesystem 但注意 Windows 上的编码问题”并不是初学者友好的教学方式。
Zig 编程语言证明了,当配合使外部库更易于访问的生态系统基础设施时,一个小而专注的标准库并非限制,而是优势。
C++ 面临着不同的结构性现实:没有统一的包管理器,ABI 稳定性约束,以及几十年的部署代码。这些约束是真实的。但它们并没有改变基本的经济学原理。每添加一个组件到标准库,就会产生一个永久的义务。每个义务消耗有限的委员会带宽。每一小时用于维护那些被后悔的添加,都是浪费在了无法为整个 C++ 社区带来好处的工作上。
委员会最宝贵的资源是其集体的专业知识和关注力。一种保护这一资源的哲学——在接受永久义务之前要求严格的证据——比扩展标准库并希望广度能弥补生态系统基础设施缺失的方式更能服务 C++ 社区。
Zig 提出了这个问题:“这个组件应该在标准库中吗,还是生态系统能够处理?” C++ 应该同样提出这个问题,并对每个库提案应用同样的严格标准。
• Kelley, Andrew. Zig 编程语言简介
• Zig std-lib-orphanage. 已归档于 2025 年 11 月。
• Ziggit: 标准库是否应该包含“电池”功能?. 2024。
• Burja, Samo. 大创始人理论. 2020。
• [P3001R0] Muller, Jonathan; Laine, Zach; Lelbach, Bryce Adelstein; Sankel, David. “std::hive 和类似的容器不适合标准库。” 2023 年 10 月。
• [P2028R0] Winters, Titus. “ABI是什么,WG21 应该怎么做?” 2020。
• [P1863R0] Winters, Titus. “ABI - 现在或永远。” 2019。
• [P0939R4] Dos Reis, Gabriel. “ISO C++ 的发展方向。”
• Jabot, Corentin. “为你的樱桃做蛋糕:什么应该进入 C++ 标准库?”
• Winters, Titus. “C++ 标准库应该包括什么。” Abseil 博客。
• R0 (2026-02-06): 初步草稿,探讨 Zig 的标准库哲学及其对 WG21 的适用性。
--end--

浙公网安备 33010602011771号