Skip to content
This repository was archived by the owner on Aug 24, 2024. It is now read-only.

Translate code comments #34

Merged
merged 2 commits into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions 02-language-overview-part1.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Zig 代码如下所示:
```zig
const std = @import("std");

// This code won't compile if `main` isn't `pub` (public)
// 如果 `main` 不是 `pub` (public),此代码将无法编译
pub fn main() void {
const user = User{
.power = 9001,
Expand Down Expand Up @@ -87,7 +87,7 @@ const MAX_POWER = user.MAX_POWER
下面这行 Zig 代码是一个注释:

```zig
// This code won't compile if `main` isn't `pub` (public)
// 如果 `main` 不是 `pub` (public),此代码将无法编译
```

Zig 没有像 C 语言中类似 `/* ... */` 的多行注释。
Expand Down Expand Up @@ -190,10 +190,10 @@ pub const User = struct {
方法只是普通函数,只是说可以用 `struct.method()` 方式调用。以下两种方法等价:

```zig
// call diagnose on user
// 在 user 上调用 diagnose
user.diagnose();

// The above is syntactical sugar for:
// 以上是这行代码的语法糖:
User.diagnose(user);
```

Expand Down Expand Up @@ -271,11 +271,12 @@ pub fn init(name: []const u8, power: u64) User {
```zig
const a = [5]i32{1, 2, 3, 4, 5};

// we already saw this .{...} syntax with structs
// it works with arrays too
// 我们已经在结构体中使用过 .{...} 语法,
// 它也适用于数组

const b: [5]i32 = .{1, 2, 3, 4, 5};

// use _ to let the compiler infer the length
// 使用 _ 让编译器推断长度
const c = [_]i32{1, 2, 3, 4, 5};
```

Expand Down Expand Up @@ -320,7 +321,7 @@ pub fn main() void {
为了解决这个问题,你可能会想要进行以下更改:

```zig
// replace const with var
// const 替换为 var
var b = a[1..end];
```

Expand Down Expand Up @@ -403,7 +404,7 @@ std.debug.print("{s}'s power is {d}\n", .{user.name, user.power});
你可能想知道上面这行代码中需要编译时执行的是什么。`print` 函数的定义要求我们的第一个参数(字符串格式)是编译时已知的:

```zig
// notice the "comptime" before the "fmt" variable
// 注意变量"fmt"前的"comptime"
pub fn print(comptime fmt: []const u8, args: anytype) void {
```

Expand Down
22 changes: 11 additions & 11 deletions 03-language-overview-part2.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ Zig 的控制流很可能是我们所熟悉的,但它与 Zig 语言的其他
Zig 中,`if`、`else if` 和 `else` 也很常见:

```zig
// std.mem.eql does a byte-by-byte comparison
// for a string it'll be case sensitive
// std.mem.eql 对字符串进行区分大小写的一个一个字节地比较
if (std.mem.eql(u8, method, "GET") or std.mem.eql(u8, method, "HEAD")) {
// handle a GET request
// 处理 GET 请求
} else if (std.mem.eql(u8, method, "POST")) {
// handle a POST request
// 处理 POST 请求
} else {
// ...
}
Expand Down Expand Up @@ -156,10 +155,11 @@ while (i < src.len) {
var i: usize = 0;
var escape_count: usize = 0;

// this part
// 改写后的
while (i < src.len) : (i += 1) {
if (src[i] == '\\') {
// +1 here, and +1 above == +2
// 这里 +1,上面也 +1,相当于 +2
i += 1;
escape_count += 1;
}
Expand Down Expand Up @@ -199,7 +199,7 @@ const personality_analysis = blk: {
枚举是带有标签的整数常量。它们的定义很像结构体:

```zig
// could be "pub"
// 可以是 "pub"
const Status = enum {
ok,
bad,
Expand Down Expand Up @@ -341,9 +341,9 @@ if (home) |h| {

```zig
const h = home orelse "unknown"
// or maybe
// 或者可能

// exit our function
// 离开函数
const h = home orelse return;
```

Expand Down Expand Up @@ -373,8 +373,8 @@ std.crypto.random.bytes(&pseudo_uuid);
Zig 中错误处理功能十分简单、实用。这一切都从错误集(error sets)开始,错误集的使用方式类似于枚举:

```zig
// Like our struct in Part 1, OpenError can be marked as "pub"
// to make it accessible outside of the file it is defined in
// 与第 1 部分中的结构一样,OpenError 也可以标记为 "pub"
// 使其可以在其定义的文件之外访问
const OpenError = error {
AccessDenied,
NotFound,
Expand Down Expand Up @@ -475,7 +475,7 @@ try action(req, res);
函数同时返回可选类型与错误联合类型的情况并不少见。在推导错误集的情况下,形式如下:

```zig
// load the last saved game
// 载入上次保存的游戏
pub fn loadLast() !?Save {
// TODO
return null;
Expand Down
17 changes: 9 additions & 8 deletions 07-heap-memory-and-allocator.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ fn allocLower(allocator: Allocator, str: []const u8) ![]const u8 {
上面的代码没问题。但以下用法不是:

```zig
// For this specific code, we should have used std.ascii.eqlIgnoreCase
// 对于这个特定的代码,我们应该使用 std.ascii.eqlIgnoreCase
fn isSpecial(allocator: Allocator, name: [] const u8) !bool {
const lower = try allocLower(allocator, name);
return std.mem.eql(u8, lower, "admin");
Expand Down Expand Up @@ -211,7 +211,7 @@ pub const User = struct {
在这种情况下,返回一个 `User`可能更有意义。但有时你会希望函数返回一个指向它所创建的东西的指针。当你想让生命周期不受调用栈的限制时,你就会这样做。为了解决上面的悬空指针问题,我们可以使用`create` 方法:

```zig
// our return type changed, since init can now fail
// 我们的返回类型改变了,因为 init 现在可以失败了
// *User -> !*User
fn init(allocator: std.mem.Allocator, id: u64, power: i32) !*User{
var user = try allocator.create(User);
Expand Down Expand Up @@ -284,7 +284,7 @@ pub fn main() !void {
const T = std.heap.GeneralPurposeAllocator(.{});
var gpa = T{};

// is the same as:
// 等同于:

var gpa = std.heap.GeneralPurposeAllocator(.{}){};
```
Expand Down Expand Up @@ -406,12 +406,12 @@ Test [1/1] test.IntList: add... [gpa] (err): memory address 0x101154000 leaked:
此处有多个内存泄漏。幸运的是,测试分配器准确地告诉我们泄漏的内存是在哪里分配的。你现在能发现泄漏了吗?如果没有,请记住,通常情况下,每个 `alloc` 都应该有一个相应的 `free`。我们的代码在 `deinit` 中调用 `free` 一次。然而在 `init` 中 `alloc` 被调用一次,每次调用 `add` 并需要更多空间时也会调用 `alloc`。每次我们 `alloc` 更多空间时,都需要 `free` 之前的 `self.items`。

```zig
// existing code
// 现有的代码
var larger = try self.allocator.alloc(i64, len * 2);
@memcpy(larger[0..len], self.items);

// Added code
// free the previous allocation
// 添加的代码
// 释放先前分配的内存
self.allocator.free(self.items);
```

Expand Down Expand Up @@ -490,8 +490,9 @@ const aa = arena.allocator();

var list = try IntList.init(aa);

// I'm honestly torn on whether or not we should call list.deinit.
// Technically, we don't have to since we call defer arena.deinit() above.
// 说实话,我很纠结是否应该调用 list.deinit。
// 从技术上讲,我们不必这样做,因为我们在上面调用了 defer arena.deinit()。

defer list.deinit();

...
Expand Down
30 changes: 13 additions & 17 deletions 09-coding-in-zig.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ const User = struct {
上述代码虽然区分大小写,但无论我们如何完美地输入 `Leto`,`contains` 总是返回 `false`。让我们通过遍历 `lookup` 打印其值来调试一下:

```zig
// Place this code after the while loop
// 将这段代码放在 while 循环之后

var it = lookup.iterator();
while (it.next()) |kv| {
Expand Down Expand Up @@ -184,7 +184,7 @@ false
对于上述代码,实际上只有一种解决方案:我们的 `lookup` 必须拥有键的所有权。我们需要添加一行并修改另一行:

```zig
// replace the existing lookup.put with these two lines
// 用这两行替换现有的 lookup.put
const owned_name = try allocator.dupe(u8, name);

// name -> owned_name
Expand All @@ -198,9 +198,7 @@ try lookup.put(owned_name, .{.power = i});
唯一的解决办法就是自己释放键值。在这一点上,创建我们自己的 `UserLookup` 类型并在 `deinit` 函数中封装这一清理逻辑可能会比较合理。一种简单的改法:

```zig
// replace the existing:
// defer lookup.deinit();
// with:
// 用以下的代码替换现有的 defer lookup.deinit();
defer {
var it = lookup.keyIterator();
while (it.next()) |key| {
Expand Down Expand Up @@ -367,9 +365,8 @@ pub fn main() !void {
`anytype` 的一个最大缺点就是文档。下面是我们用过几次的 `std.json.stringify` 函数的签名:

```zig
// I **hate** multi-line function definitions
// But I'll make an exception for a guide which
// you might be reading on a small screen.
// 我**讨厌**多行函数定义
// 不过,如果你在小屏幕上阅读,我会破例

fn stringify(
value: anytype,
Expand Down Expand Up @@ -456,7 +453,7 @@ zig build install -Doptimize=ReleaseSmall -Dtarget=x86_64-windows-gnu
除了默认的『安装』步骤外,可执行文件通常还会增加两个步骤:『运行』和『测试』。一个库可能只有一个『测试』步骤。对于基本的无参数即可运行的程序来说,只需要在构建文件的最后添加四行:

```zig
// add after: b.installArtifact(exe);
// 在这行代码后添加下面的代码: b.installArtifact(exe);

const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
Expand Down Expand Up @@ -501,8 +498,7 @@ Zig 的内置软件包管理器相对较新,因此存在一些缺陷。虽然
首先,新建一个名为 `calc` 的文件夹并创建三个文件。第一个是 `add.zig`,内容如下:

```zig
// Oh, a hidden lesson, look at the type of b
// and the return type!!
// 哦,这是一节隐藏的课程,看看 b 的类型和返回类型!!

pub fn add(a: anytype, b: @TypeOf(a)) @TypeOf(a) {
return a + b;
Expand Down Expand Up @@ -555,8 +551,8 @@ pub fn build(b: *std.Build) !void {
回到我们的 `learning`项目和之前创建的 `build.zig`。首先,我们将添加本地 `calc` 作为依赖项。我们需要添加三项内容。首先,我们将创建一个指向 `calc.zig`的模块:

```zig
// You can put this near the top of the build
// function, before the call to addExecutable.
// 你可以把这些代码放在构建函数的顶部,
// 即调用 addExecutable 之前。

const calc_module = b.addModule("calc", .{
.source_file = .{ .path = "PATH_TO_CALC_PROJECT/calc.zig" },
Expand All @@ -572,7 +568,7 @@ const exe = b.addExecutable(.{
.optimize = optimize,
.root_source_file = .{ .path = "learning.zig" },
});
// add this
// 添加这些代码
exe.addModule("calc", calc_module);
b.installArtifact(exe);

Expand All @@ -583,7 +579,7 @@ const tests = b.addTest(.{
.optimize = optimize,
.root_source_file = .{ .path = "learning.zig" },
});
// add this
// 添加这行代码
tests.addModule("calc", calc_module);
```

Expand Down Expand Up @@ -625,12 +621,12 @@ _ = b.addModule("calc", .{
要使用这一依赖关系,我们需要对 `build.zig` 进行一处修改:

```zig
// replace this:
// 将这些代码:
const calc_module = b.addModule("calc", .{
.source_file = .{ .path = "calc/calc.zig" },
});

// with this:
// 替换成:
const calc_dep = b.dependency("calc", .{.target = target,.optimize = optimize});
const calc_module = calc_dep.module("calc");
```
Expand Down