当出现 returns 错误时,您可以重试 Zig 函数调用吗?

Can you retry a Zig function call when it returns an error?

Zig 的文档显示了不同的错误处理方法,包括将错误值冒泡到调用堆栈、捕获错误并使用默认值、恐慌等。

我正在尝试弄清楚如何重试提供错误值的函数。

例如,在 ziglearn 的以下代码片段中,是否有办法在用户输入超过 100 个字符的情况下重试 nextLine 函数?

fn nextLine(reader: anytype, buffer: []u8) !?[]const u8 {
    var line = (try reader.readUntilDelimiterOrEof(
        buffer,
        '\n',
    )) orelse return null;
    // trim annoying windows-only carriage return character
    if (@import("builtin").os.tag == .windows) {
        return std.mem.trimRight(u8, line, "\r");
    } else {
        return line;
    }
}

test "read until next line" {
    const stdout = std.io.getStdOut();
    const stdin = std.io.getStdIn();

    try stdout.writeAll(
        \ Enter your name:
    );

    var buffer: [100]u8 = undefined;
    const input = (try nextLine(stdin.reader(), &buffer)).?;
    try stdout.writer().print(
        "Your name is: \"{s}\"\n",
        .{input},
    );
}

这应该可以满足您的要求。

const input = while (true) {
   const x = nextLine(stdin.reader(), &buffer) catch continue;
   break x;
} else unreachable; // (see comment) fallback value could be an empty string maybe?

分解:

  • 而不是try,你可以使用catch来做一些错误的事情,我们在这种情况下重新开始循环。
  • while 循环也可以用作表达式,您可以 break 从它们中获取一个值。他们还需要一个 else 分支,以防循环结束而不脱离它。在我们的例子中这是不可能的,因为我们将永远循环直到 nextLine 成功,但是如果我们有另一个退出条件(比如重试次数限制),那么我们需要提供一个“后备”值,而不是unreachable.

您也可以将其设为 one-liner:

const input = while (true) break nextLine(stdin.reader(), &buffer) catch continue else unreachable;

希望新的 self-hosted 编译器能够意识到 else 分支不是必需的这一事实,因为我们将永远中断值循环。