在 Zig 0.8.0 中,当切换 u8 字符以获取枚举类型时,我在这段代码中遇到了一个奇怪的编译器错误:
.op_type = switch(c1) {
'+' => .add, '-' => .sub,
'*' => .mul, '/' => .div,
'%' => .mod, '^' => .exp,
'|' => .bor, '~' => .bxor,
'&' => .band,
'<' => if (is_long) .lte else .lt,
'>' => if (is_long) .gte else .gt,
'=' => if (is_long) .eq else .nop,
'!' => if (is_long) .neq else return TokenError.NotAToken,
else => unreachable
}
错误是:
.\lib.zig:137:36: error: values of type '(enum literal)' must be comptime known
'<' => if (is_long) .lte else .lt,
^
通常在 zig 中,“ must be comptime known
”消息意味着我在运行时值上留下了类型签名,例如const x = 3;
. 但是,switch 表达式中没有签名,编译器无论如何都应该知道类型是什么,因为该字段.op_type
采用Op
类型枚举。
我能够通过使用 switch 语句而不是用于分配占位符值的表达式来解决该问题。结果很惨:
var op_type: Op = undefined;
switch(c1) {
'+' => op_type = .add, '-' => op_type = .sub,
'*' => op_type = .mul, '/' => op_type = .div,
'%' => op_type = .mod, '^' => op_type = .exp,
'|' => op_type = .bor, '~' => op_type = .bxor,
'&' => op_type = .band,
'<' => if (is_long) {op_type = .lte;} else {op_type = .lt;},
'>' => if (is_long) {op_type = .gte;} else {op_type = .gt;},
'=' => if (is_long) {op_type = .eq ;} else {op_type = .nop;},
'!' => if (is_long) {op_type = .neq;} else return TokenError.NotAToken,
else => unreachable
}
...
... {
...
.op_type = op_type
}
我发布这个问题的原因是我并不真正理解第一个实现的问题,我想看看是否有比我想出的更好的解决方案。