Zig 语言初探
为什么选择 Zig
我曾经做过各种各样的项目,也使用各种语言。大体的原因是一些任务只有某种语言的库或者框架的实现,比如开发一个进行图像处理的 iOS App,你只能使用 OpenCV+ObjC,用 Keras 训练一个模型,也只能用 Python,所以可以说我没得选。
过去几年里,我的主要身份是一个 JS 全栈工程师,开发网页内的文本/代码编辑器,还要满足一些实时渲染 Markdown/Latex 的效果,这个过程需要用到 peg.js 去实现一个小的 parser,识别简单的语法错误并协助 Markdown/Latex 的渲染。在这个过程中加深了我对编译器的理解,并且想要设计一个编译器,以及虚拟机。显然这个靠 JS 是不够的。
考虑到性能和开发速度平衡的场景,我有了几种选择:C,Go,Rust 和 Zig。其中 Zig 是我在学 Rust 的时候了解到的。
除此以外,还有很多种宣称自己又快又优雅的语言,比如 Haskell,Erlang,OCaml 等等函数式语言。它们都是基于虚拟机的,并且相信经过了数十年的优化,这些虚拟机一定是非常高效的。但是「快」是个相对概念,必须结合场景或用途来探讨。比如用 Erlang/OTP 可以快速整出一个适用于高并发高可用场景的消息队列而 C 显然就不行,但用 Erlang 实现一个正则表达式引擎呢?
所以当你设计的是一个系统工具的时候,几乎就没有选择了,只剩下 C, Rust 和 Zig。在这三者中我最看重的是这门语言的设计是否是在有意协助开发者。C 显然不是,并且 C 的语义和标准库的支持已经有点跟不上时代了,并且运行时的错误很难发现,因此只剩下 Rust 和 Zig 之间的比较。
Rust 和 Zig 的比较较为有趣。我学过一段时间 Rust,尤其是试图理解 Lifetime 的时候遇到很大困难,并且觉得用 Rust 会遇到很大问题,这个时候我遇到了 Zig,并且看到 Zig 的介绍感到很能说明问题,Zig 的设计者认为程序员要调试程序,而不是要调试自己关于编程语言的知识。Rust 虽然有丰富的语法避免了 dangling pointer 和 double free 等问题,但很显然在未来选择 Rust 开发之后,会有大量的时间消耗在调试我没有正确理解语法而导致的错误上,这样很耽误事儿。
Zig 的语法很简单,但是使用 Zig 写出来的代码未必很简洁。这是我认为 Zig 设计者(Andrew R Kelley)很厉害的地方,Zig 设计者有一个非常固执的坚持,就是不能引入隐式控制。什么是隐式控制呢?比如在 JavaScript 中可以使用for..of
来迭代一个结构,只要这个结构支持 Iterator 协议就可以,具体来说就是一个包含.next()
方法的对象,那么在for..of
循环中,你不需要调用.next()
方法,就可以顺滑地得到每次.next()
的返回值。但是在 Zig 设计者看来,这便是隐式控制了。在他看来,Zig 不应该支持程序员对控制流进行抽象,这当然会使得代码变得不那么简洁美观,但是代码能够自我显明意图比简洁美观更重要。在 GitHub 上有很多人对 Zig 很感兴趣,并且提出了各种各样的 proposal 希望把 XXX 语言的 XXX 特性加进来,但是都被 Andrew 回绝了。
这是我认为 Zig 胜于 Rust 的地方,就是它是强迫程序员用简单直观的语言来详细地描述逻辑,而不是强迫程序员先掌握一门复杂的语法。
版权声明: 本文为 InfoQ 作者【Yuet】的原创文章。
原文链接:【http://xie.infoq.cn/article/d0a87f862e687fac59031bc77】。文章转载请联系作者。
评论