202311 | 传值或传引用,这是个大问题
重大事件
本月讨论比较多的就是 Zig May Pass Anything By Reference 这篇文章了。
它讲述了 Zig 里面一个比较有争议的点,函数的参数到底是传值还是传引用。
|
|
上面这个例子修改了 b
参数的值,但是打印出来的 a
的值也被修改了。
传值的好处就是不用担心原值会被修改,传引用的好处就是可以减少数据拷贝的代价。但是 Zig 目前采用的方式是由编译器推导来决定合适的方式。这样的目的是减少程序员负担,但这实际上会给程序带来不确定性,比如上述例子。
Andrew 在 Lobster 上回复了这个问题,确实是一个比较严重的问题,一种解法是分析一个变量有多少个 alias,编译器只在确定没问题时才进行优化,但是分析一个变量的 alias 有多少不是件容易的事。
其他语言如 C/C++/Rust 等没有进行这种优化尝试,因此没有这个问题,但是 Zig 作为一个新的语言,想尝试来用一种程序员无感的方式来解决,只是目前还没有想到更完善的方案而已。
一些熟悉 Zig zen 的读者可能会觉得这违背了第一条『Communicate intent precisely』,目前来看确实是这样的,而且 core team 老早就意识到这个问题了,感兴趣的读者可以参考:
观点/教程
- Zig's std.json.Parsed(T)
老朋友 openmymind 的文章,这篇文章主要讲述了使用 Zig 中的 json 库序列化后,如何更好的使用返回值,由于有一个 allocator 参数,因此比不能简单的返回
T
,作者这里定义了一个Managed
来解决:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
pub fn Managed(comptime T: type) type { return struct { value: T, arena: *std.heap.ArenaAllocator, const Self = @This(); pub fn fromJson(parsed: std.json.Parsed(T)) Self { return .{ .arena = parsed.arena, .value = parsed.value, }; } pub fn deinit(self: Self) void { const arena = self.arena; const allocator = arena.child_allocator; arena.deinit(); allocator.destroy(arena); } }; }
- Factor is faster than Zig!
- 一个有意思的案例分享。
- A day with Zig
作者把之前一个 Go 的项目转成 Zig,这里介绍了一些感受,
- 文档缺乏
- 文件级别导入
- @fieldParentPtr
- 对
@fieldParentPtr
使用的介绍 - Generating documentation from zig build
作者在这篇文章里尝试在 zig build 文件中输出文档,目前步骤略微繁琐。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
const std = @import("std"); pub fn build(b: *std.Build) void { const exe = b.addExecutable(.{ .name = "myprogram", .root_source_file = .{ .path = "src/main.zig" }, .target = b.standardTargetOptions(.{}), .optimize = b.standardOptimizeOption(.{}), }); b.installArtifact(exe); const install_docs = b.addInstallDirectory(.{ .source_dir = exe.getEmittedDocs(), .install_dir = .prefix, .install_subdir = "docs", }); const docs_step = b.step("docs", "Copy documentation artifacts to prefix path"); docs_step.dependOn(&install_docs.step); }
- What's Zig got that C, Rust and Go don't have? (with Loris Cro)
- [视频] Loris 参与的一档播客
- A Simple Example of Calling a C Library from Zig
- 一个简明的教程,演示 Zig 如何引用 C 类库
- What is the Zig philosophy on APIs and abstraction?
一个 Reddit 帖子,讨论 Zig 的在 API 设计上的哲学、理念。一个有意思的点是 Zig 不支持私有的字段,全部都是 public 的。Andrew 在 Proposal: Private Fields #9909 这个 issue 里面讨论过原因,主要根据:
- 一个结构体的抽象,很难保证不泄漏,比如一个类型的 align、size,一个函数是否可以在 comptime 执行
- 一个包的兼容性,应该由文档来解释
- 增加私有字段,会增加语言的复杂度,而且这种复杂性本身是完全可以避免的
项目/工具
- zig build explained – building C/C++ projects
- 经典文章回顾,如何使用 Zig 构建系统编译 C/C++ 项目
- akhildevelops/cudaz
- A Zig Cuda wrapper