Skip to content

Latest commit

 

History

History
102 lines (85 loc) · 5.54 KB

202311.org

File metadata and controls

102 lines (85 loc) · 5.54 KB

202311 | 传值或传引用,这是个大问题

重大事件

本月讨论比较多的就是 Zig May Pass Anything By Reference 这篇文章了。

它讲述了 Zig 里面一个比较有争议的点,函数的参数到底是传值还是传引用。

const AAAA = struct {
    foo: [100]u32,
};

fn aaaaa(a: AAAA, b: *AAAA) void {
  b.*.foo[0] = 5;

  std.debug.print("wtf: {}", .{ a.foo[0] });
}

pub fn main() !void {
    var f: AAAA = undefined;

    f.foo[0] = 0;

    aaaaa(f, &f);
}

上面这个例子修改了 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 来解决:
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 文件中输出文档,目前步骤略微繁琐。
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