HeadlinesBriefing HeadlinesBriefing.com

Zig 中的 Trait:编译期抽象

Hacker News •
×

最近我有更多时间用 Zig 编写代码,这对我的身心都很有益。本文分享了作者在 Zig 中使用抽象的一些见解,包括一些作者觉得很有用、但在更广泛的范围内却很少见到的技巧。

关于 Zig 的接口已有大量讨论,这也是理所当然的。虽然接口并不是语言特性,但它实际上是在 Zig 中实现运行时多态的方式。关于 Zig 的 comptime 以及如何利用它来避免动态分派的性能问题,并编写简洁的、面向数据的代码,也已有很多论述。

Zig 中的多态通常通过两种方式获得。动态接口使用不透明指针、虚表和动态分派来实现运行时多态。编译期鸭子类型则使用类型反射、switch 语句和编译期单态化来实现静态多态。这种现状已经证明是有效的,但并非没有权衡。接口提供了其他语言中熟悉的类型契约,但由于它们在运行时是模块化的,因此会给编译器带来难以逾越的障碍,从而产生性能开销。对于性能关键的代码,Zig 通常依赖编译期鸭子类型,它可以在编译时发现接口违规,但仍需要仔细地为契约编写文档。

来自 Rust trait 或 Haskell 类型类的开发者可能会觉得这种安排过于简单,而 Zig 的确以简单为目标。作者认为,只要稍作调整,在 Zig 用户态代码中就可以实现类似的类型抽象。该提案提出了一种新的约定,即把编译期类型契约定义为 Trait,无需任何库或额外机制。它的灵感来源于函数式编程的整体思想,尤其是 OCaml。

Trait 被定义为一个编译期结构体,其中包含针对给定类型的相关函数。文章以用于折叠的 Reducer Trait 为例进行说明:一个类型在空值和合并操作之下构成一个 reducer。针对 i32 分别定义的 sum 与 product Trait 表明,同一套泛型 reduce 逻辑可以被复用,并且编译器能够对循环进行内联和展开。作者最后总结道:Trait 不过是一袋乐趣罢了。

来源: Hacker News · 由HeadlinesBriefing整理摘要