为什么是Zig?
No hidden control flow
无隐藏控制流
如果Zig的代码看起来不像是要跳走去调用一个function,那么他就不是,这意味着下面的代码你可以确保的是调用只有foo()然后bar(),这确保了不需要知道任何类型的东西:
var a = b + c.d;foo();bar();
隐藏控制流的示例:
- D语言有
@property函数,这是当你调用看起来像是属性访问时的方法,所以在上面的示例中,c.d可能是调用了一个函数。 - C++,D和Rust有操作符重载,因此
+操作符调用了一个函数。 - C++, D 和Go 有
throw/catch异常,所以foo()会抛出一个异常,阻止bar()被调用。(当然了,在Zig中foo()也会死锁,阻止bar()函数执行,这可能发生在任何图灵完备的语言中)。
No hidden allocations
无隐藏内存分配
当遇到堆内存分配Zig有一种不干涉的方式。这里没有新的关键字或者新的语言特性用于堆内存分配。(例如string链接操作符)。堆的整个概念是被应用程序代码和库管理的,而不是通过语言。
隐藏分配的示例:
- Go的defer操作会分配内存到一个本地函数栈中。如果您在循环中使用defer,那么它除了是这种控制流工作的一种不直观的方式之外,还会导致内存不足故障。
- C++协程会为了调用协程分配堆内存。
- 在Go中,一个函数调用也会引起堆分配,这是因为go线程会分配小的堆栈,当调用栈足够深,调用堆栈会调整大小。
- 主要的Rust标准类库API恐慌于内存溢出情况,可替换的API接受分配符参数都是一个事后的想法。(参考链接)
几乎所有的垃圾回收语言都有隐藏的内存分配,是由于垃圾回收器隐藏了在清理方面的证据。
隐藏分配最主要的问题是它阻止了代码的可重用性,不必要的限制了代码可以部署运行的环境。简而言之,有很多的用户案例有可能依赖于控制流程和函数调用来避免内存分配的副作用,因此编程语言只有在能够切实地提供这种保证的情况下才能为这些用例服务。
在Zig中,有标准类库提供了和处理堆内存分配器,但这是可选的标准类库特性,不是语言本身带来的。如果你没有初始化一个堆内存分配器,你可以非常自信你的项目不会有内存分配。
First-class support for no standard library
A Portable Language for Libraries
A Package Manager and Build System for Existing Projects
Simplicity
Tooling
工具

参考:

