一个写了十多年 Haskell 的函数式程序员,突然说自己以后会写很多 Zig。这个转向有意思。
他不是在夸 Zig “够快”。系统语言被夸性能,已经没什么信息量。扎眼的是,他夸的是函数式程序员真正在意的东西:表达能力、构造正确性的空间,以及更少的语义惊吓。
这篇博客的价值也在这里。它没有证明 Zig 能替代 Haskell、Rust 或 C++。它至少表明,在 GC 成本、类型系统复杂化和硬件瓶颈一起挤压开发者时,一门更朴素、更显式的语言,开始重新获得吸引力。
这篇文章到底夸 Zig 什么
作者评价语言,大致沿着三条轴线走:表达领域概念时有多少噪音,类型系统能不能帮助构造正确性,以及写到什么时候现实开始和理解分叉。
他看上 Zig,也不是因为 Zig 把 Haskell 搬到了系统编程里。恰好相反,Zig 很少“仙气”。它把很多东西摊开给你看。
| 作者关心的轴线 | 在 Haskell 里常见的答案 | Zig 戳中的地方 | 代价 |
|---|---|---|---|
| 表达领域噪音 | 高层抽象、类型类、代数数据类型 | comptime 能生成类型逻辑,减少重复代码 | 写法更啰嗦,更显式 |
| 正确性 / 类型系统可编程性 | correct-by-construction,靠类型表达约束 | comptime 可写约束、自定义编译错误、模拟部分类型级模式 | 静态保证不等同于 Haskell 或 Rust |
| mean-time to surprise | 依赖运行时、惰性、抽象组合的理解成本 | Zig 强调 no spooky action at a distance | 程序员要直面内存和资源 |
这里最该避免的误读,是把这篇文章读成“函数式程序员集体转向 Zig”。没有这个证据。
它更像一个重度 Haskell 用户的实验后判断:当抽象继续加厚,硬件和调试开始索要成本时,显式反而变成一种工程优势。
受影响最大的不是普通应用开发者,而是两类人。
一类是函数式程序员。尤其是那些喜欢 Haskell 的表达力,但又不得不处理性能、部署体积、内存行为的人。Zig 值得他们拿来做小工具、CLI、解析器、性能敏感模块,而不是马上迁移主业务。
另一类是系统语言使用者。尤其是正在 C、C++、Rust 之间犹豫的团队。Zig 给出的不是最强类型安全,也不是最大生态,而是一条更容易看清资源边界的路线。
分水岭在 comptime、Allocator 和 IO
comptime 是作者最重视的入口。
在 Zig 里,编译期不是单纯的宏替换。它可以参与类型构造、生成约束、给出自定义编译错误。作者认为,它能模拟 Haskell 里的 newtype、Maybe / sum type,也能用 struct 做出类似 typeclass dictionary 的东西。
但要注意,是“模拟”,不是复刻。
Haskell 帮你隐式传递的 typeclass dictionary,在 Zig 里往往要自己摆出来。Zig 的写法更笨、更直,也更少魔术。喜欢高度抽象的人会嫌它重,怕隐式行为的人会觉得安心。
Allocator 是第二个关键点。
作者对 GC 的批评很直接:GC 降低心智负担,也减少大量样板代码;但它可能制造一片堆指针森林,抬高性能天花板,还会让程序员慢慢忘记机器如何执行程序。
这不能写成“GC 失败了”。GC 没失败。Java、Go、JavaScript 仍然支撑着巨量生产系统。
变化在边际。现代硬件里,CPU 计算能力增长很快,内存访问和缓存局部性越来越像硬约束。指针乱跳、运行时暂停、对象布局不可控,以前能忍,现在更疼。
Zig 的 Allocator 把这笔账写到接口上。函数需要什么分配策略,调用者就要看见它。难看一点,但少了很多远处突然冒出来的账单。
Zig 0.16 的 IO 接口也让作者眼前一亮。示例里,HTTP client 显式接收 allocator 和 io。作者把这类设计类比为 Reader / IO monad:计算依赖的上下文被传进来,而不是藏在运行时背后。
这里别把 monad 讲成语法糖。作者强调的是,monad 可以描述命令式计算所依赖的上下文。Zig 没有采用 Haskell 的形式,却在工程接口上给出了相似方向:资源、环境、IO,不要假装不存在。
这对开发者的实际动作很具体。
如果你在写一次性脚本、后台 CRUD、依赖复杂生态的业务系统,Zig 未必带来立刻收益。GC 和成熟框架仍然更省人。
如果你在写性能敏感工具、嵌入式组件、运行时库、编译器相关工具,或者需要严控内存和 IO 边界的服务,Zig 值得试一个小项目。别先谈迁移,先看团队能不能接受显式资源管理带来的日常成本。
我的判断:Zig 的价值不在优雅,在把抽象拽回机器
我更在意的,不是一个 Haskell 用户喜欢上 Zig,而是他为什么会喜欢。
很多现代语言都在努力把机器藏起来。GC 藏内存,运行时藏调度,类型推导藏样板,trait 和宏藏重复逻辑。这些设计都有效。没有它们,很多大型软件根本写不动。
问题在于,账单不会消失。
“天下熙熙,皆为利来。”语言设计也一样。抽象有收益,就会有成本。成本有时寄给 CPU cache,有时寄给尾延迟,有时寄给调试的人。
Zig 做的事不浪漫。它让 allocator 出现在函数签名里,让 IO 作为接口传进去,让 comptime 的能力通过更直白的代码暴露出来。它没有把开发者从机器里彻底解放出来,反而提醒你:机器一直在那里。
这也是它和 Rust 的差别。
Rust 用所有权和借用检查,在编译期尽量堵住内存安全问题。它的静态保证很强,代价是学习曲线和类型系统复杂度。
Zig 更少这种强约束。它的赌注是简单模型、显式资源、可控边界。它不一定更安全,也不一定更适合大团队,但它更容易让程序员知道自己在付什么钱。
所以我不建议把这篇博客读成“该从 Haskell/Rust/C++ 换到 Zig”。证据不够,现实也不支持。
更合理的读法是:Zig 适合成为函数式程序员的第二语言实验田。用它检验一件事:离开 GC 和高阶类型魔法后,你还能不能保留足够多的抽象能力,同时把资源成本看清楚。
接下来最该观察三件事。
| 观察点 | 为什么重要 | 可能影响谁 |
|---|---|---|
| Zig 0.16 IO 接口的稳定性 | IO 上下文显式化能否在真实项目里站住 | 写网络库、工具链、运行时组件的人 |
| comptime 抽象的可维护性 | 能否少写重复代码,又不制造新魔法 | 函数式程序员、库作者 |
| Allocator 模式的团队成本 | 显式内存策略是否会拖慢协作 | 想用 Zig 替代部分 C/C++ 的团队 |
如果这三点跑通,Zig 的吸引力会很实在。不是因为它更漂亮,而是因为它在性能、可理解性和抽象之间,给了一种比较硬的折中。
如果跑不通,Zig 也不会因此失去价值。它至少把一个问题摆清楚了:当硬件瓶颈从“算不动”变成“搬不快”,语言继续把机器模型包得严严实实,开发者迟早要在调试和性能里补课。
这篇博客真正好看的地方,是一个 Haskell 老兵没有抛弃抽象。他只是开始怀疑,抽象的默认付款方式是不是该改了。
