Zig
保持高级语言表达能力的同时,把
数据如何表示、代码何时生成、运行时发生什么尽可能交还给程序员
| 维度 | Zig 的选择 |
|---|---|
| 数据如何存在 | 显式布局与表示 |
| 代码如何复用 | comptime 生成和特化 |
| 运行时如何变化 | 显式函数指针、tagged union、vtable |
| 资源如何管理 | 显式 allocator 与生命周期 |
| 错误如何传播 | 显式 error union |
| 成本在哪里发生 | 尽可能可从源码判断 |
- 简单(代码所见即所得):调试代码,而不是调试编程语言知识(比如Rust的所有权借用、Go的GC/调度器/接口动态分派)
- 无隐藏控制流(手动管理内存+defer/errdefer释放资源;!T 错误路径显式化、?T空值显式化...),没有隐藏运行时
- 无隐藏内存分配(内存分配是显式的,如果一个函数内部需要分配堆内存,需要接收一个allocator的参数)
- 无预处理器、宏
- 基于
编译时代码执行、惰性求值的元编程:
- 编译期执行函数
- 把类型当作值一样操作(无运行时开销,类型内省)
- Comptime 会以目标平台的类型、布局与运算规则为基础,在编译期完成求值
- 以统一工具链渐进改造 C/C++ 工程:
zig build提供统一构建与跨平台编译能力- 与现有 C/C++ 项目的无缝衔接(zig替代c编译链、c使用zig模块)
comptime 编译期运算
Zig 把
类型抽象、代码生成大量放在编译期,比如泛型,反射...
- anytype 类型,用于函数参数推导,调用时确定具体类型,然后编译对应实现
- comptime + type
- comptime 可以修饰函数调用、代码块、表达式,表示这些指令需要在编译期执行;可以修饰参数,表示这个值必须在编译期已知
- 类型T也是某种值,其类型是type:参数
comptime T: type接收一个类型
应用:数据处理过程中,如果只依赖编译期已知的信息的计算,可以提前在编译期完成。
运行时动态性
- union(enum) + switch,可以看作显式的、封闭世界的动态分派
const Writer = union(enum) {
file: *FileWriter,
socket: *SocketWriter,
memory: *MemoryWriter,
pub fn write(self: Writer, data: []const u8) !usize {
return switch (self) {
.file => |w| w.write(data),
.socket => |w| w.write(data),
.memory => |w| w.write(data),
};
}
};
- 函数指针
const Callback = struct {
context: *anyopaque,
callFn: *const fn (*anyopaque, []const u8) void,
pub fn call(self: Callback, data: []const u8) void {
self.callFn(self.context, data);
}
};
- 定义 vtable
const Writer = struct {
ptr: *anyopaque,
vtable: *const VTable,
const VTable = struct {
write: *const fn (*anyopaque, []const u8) anyerror!usize,
flush: *const fn (*anyopaque) anyerror!void,
};
pub fn write(self: Writer, data: []const u8) !usize {
return self.vtable.write(self.ptr, data);
}
pub fn flush(self: Writer) !void {
return self.vtable.flush(self.ptr);
}
};NOTE: comptime 可以帮助构造运行时动态机制,比如将某个具体类型转换成符合vtable的类型(类似Go的interface)
错误处理
同rust的错误处理目标一致:错误是类型系统的一部分,不可被静默忽略;
但有区别:
E!T内建于编译器,错误E只能是error set错误集合:
- 穷举:
switch穷举所有错误 - 传播:
try向上传播给调用方 - 组合:错误集可通过
||合并或由编译器自动推断,组合轻松 - 信息:错误仅是名字(整数),无法携带丰富信息,需额外方式传递
- 恢复:就地降级(
catch |_| default_value)
dot syntax
. 经常表示让编译器从上下文推断左边缺失的类型/对象。
- 第一类是 contextual shorthand:
类型你已经知道了,我就不再写。 - 第二类是 postfix operator / member syntax
- Anonymous Struct Literals: .{}
- Anonymous Tuples and Arrays
- Enum Literal Inference: .variant
- Pointer Dereferencing: .*
struct
Zig 的 struct 不只是 data layout 它同时也是一个namespace
评论