September 03, 2023
0.11 终于在 8 月 4 号释出了,下面来看看它的一些重要改进吧。HN 讨论
对等类型解析算法得到改进,下面是一些在 0.10 中不能解析,但在 0.11 中可以解析的例子:
Peer Types | Resolved Type |
[:s]const T, []T | []const T |
E!*T, ?*T | E!?*T |
[*c]T, @TypeOf(null) | [*c]T |
?u32, u8 | ?u32 |
[2]u32, struct { u32, u32 } | [2]u32 |
*const @TypeOf(.{}), []const u8 | []const u8 |
而且现在使用 @intCast
这类 builtin 都只接受一个参数,目前类型根据上下文自动推断出来。
可以同时对多个对象进行遍历:
// 之前
for (input) |x, i| {
output[i] = x * 2;
}
// 现在
for (input, 0..) |x, i| {
output[i] = x * 2;
}
主要有两个改动:
test "@min/@max refines result type" {
const x: u8 = 20; // comptime-known
var y: u64 = 12345;
// Since an exact bound is comptime-known, the result must fit in a u5
comptime assert(@TypeOf(@min(x, y)) == u5);
var x_rt: u8 = x; // runtime-known
// Since one argument to @min is a u8, the result must fit in a u8
comptime assert(@TypeOf(@min(x_rt, y)) == u8);
}
新加的 builtin,用于判断执行是否在 comptime 环境下执行:
const global_val = blk: {
assert(@inComptime());
break :blk 123;
};
comptime {
assert(@inComptime());
}
fn f() u32 {
if (@inComptime()) {
return 1;
} else {
return 2;
}
}
test "@inComptime" {
try expectEqual(true, comptime @inComptime());
try expectEqual(false, @inComptime());
try expectEqual(@as(u32, 1), comptime f());
try expectEqual(@as(u32, 2), f());
}
之前 @xToY
形式的 builtin 现在已经改成了 @yFromX
,这样的主要好处是便于阅读(从右向左),这是草案。
现在可以直接用无 field 名字的 struct 来声明 tuple 类型:
test "tuple declarations" {
const T = struct { u32, []const u8 };
var t: T = .{ 1, "foo" };
try expect(t[0] == 1);
try expectEqualStrings(t[1], "foo");
var mul = t ** 3;
try expect(@TypeOf(mul) != T);
try expect(mul.len == 6);
try expect(mul[2] == 1);
try expectEqualStrings(mul[3], "foo");
var t2: T = .{ 2, "bar" };
var cat = t ++ t2;
try expect(@TypeOf(cat) != T);
try expect(cat.len == 4);
try expect(cat[2] == 2);
try expectEqualStrings(cat[3], "bar");
}
之前只能用 std.meta.Tuple
函数来定义:
- const testcases = [_]std.meta.Tuple(&[_]type{ []const u8, []const u8, bool }){
+ const testcases = [_]struct { []const u8, []const u8, bool }{
现在排序算法分布两类:
与堆排的快速最差情况相结合,同时在具有特定模式的输入上达到线性时间。
Zig 之前依赖 frame pointer 来做堆栈回卷,但它本身有些代价,因此线上环境可能会通过 -fomit-frame-pointer
将其禁用掉。
为了在这种情况下依然能够获取 panic 是的堆栈信息,Zig 现在支持了通过 DWARF unwind tables 和 MachO compact unwind information 来会恢复堆栈,详见:#15823。
0.11 首次正式引入了包管理器,具体解释可以参考:Zig Build System,而且很重要一点,step 之间可以并发执行,
C++ 实现的 Zig 编译器已经被彻底移除,这意味着 -fstage1
不再生效,Zig 现在只需要一个 2.4M 的 WebAssembly 文件和一个 C 编辑器即可,工作细节可以参考:Goodbye to the C++ Implementation of Zig。
虽然 Zig 编译器现在还是主要使用 LLVM 来进行代码生成,但在这次发布中,其他几个后端也有了非常大的进步:
虽然这仍是一个高度 WIP 的功能,但这一版本周期中的许多改进为编译器的增量编译功能铺平了道路。其中最重要的是 InternPool。Zig 用户大多看不到这一改动,但它为编译器带来了许多好处,其中之一就是我们现在更接近增量编译了。增量编译将是 0.12.0 发布周期的重点。
Error Handling In Zig
又一篇讨论错误处理的文章
Commiting Type Crimes in Zig
对 Zig 类型系统的另一种用法,有些和邱奇数类似。
Zig in 100 Seconds
Zig 宣传视频
Zig Build System & How to Build Software From Source • Andrew Kelley • GOTO 2023
Andrew 关于构建系统的视频,B 站链接、Youbute
Wrap your NIF with Zig
NIF 是 Elixir 中进行 FFI 调用的方式,如果用原生 C 接口来用,会需要写很多胶水代码, 作者这里用 comptime 特性来定义了一个 make_nif_wrapper
来简化 NIF 的实现,这个技巧在与 C 项目交互时十分有用。
Types and the Zig Programming Language
matklad 对 Zig 类型系统的总结
So Long, Twitter and Reddit
Andrew 的最新文章,远离社交平台!
WTF is Zig Comptime (and Inline)
Taking off with Zig: Putting the Z in Benchmark — Double Trouble