附录 B:运算符表
本附录提供 Auto 语言全部运算符的完整参考,按优先级从高到低排列。当多个运算符出现在同一表达式中时,Auto 按照此顺序进行求值。
优先级总览
优先级越高的运算符结合越紧密。同一组内的运算符大多数为左结合(另有说明的除外)。
| 优先级 | 类别 | 运算符 |
|---|---|---|
| 1(最高) | 一元前缀 | - ! * view mut ~ |
| 2 | 乘法 | * / % |
| 3 | 加法 | + - |
| 4 | 比较 | < > <= >= |
| 5 | 相等 | == != is |
| 6 | 逻辑与 | &&(别名:and) |
| 7 | 逻辑或 | ||(别名:or) |
| 8 | 空值合并 | ?? |
| 9 | 范围 | .. ..= |
| 10 | 赋值 | = += -= *= /= %= |
| 11 | 管道 | |> |
| 12(最低) | 错误传播 | 后缀 ! 后缀 ? |
详细表格
1. 一元前缀运算符
这些运算符出现在操作数之前,拥有最高优先级。
| 运算符 | 说明 | 示例 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|
- | 数值取反 | -x | -x | -x | -x | -x | 第 2 章 |
! | 逻辑非 | !flag | !flag | not flag | !flag | !flag | 第 2 章 |
* | 解引用(原始指针) | *ptr | *ptr | 不适用 | *ptr | 不适用 | 第 11 章 |
view | 借用为只读引用 | view s | &s | 不适用 | const T* | readonly | 第 11 章 |
mut | 借用为可变引用 | mut s | &mut s | 不适用 | T* | 不适用 | 第 11 章 |
~ | 异步蓝图(类型修饰符) | ~String | impl Future | Awaitable | 不适用 | Promise | 第 16 章 |
2. 乘法运算符
标准的乘法、除法和取余运算。左结合。
| 运算符 | 说明 | 示例 | 结果 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|---|
* | 乘法 | 6 * 7 | 42 | 6 * 7 | 6 * 7 | 6 * 7 | 6 * 7 | 第 2 章 |
/ | 整数除法 | 15 / 4 | 3 | 15 / 4 | 15 // 4 | 15 / 4 | Math.trunc(15/4) | 第 2 章 |
% | 取余(模运算) | 17 % 5 | 2 | 17 % 5 | 17 % 5 | 17 % 5 | 17 % 5 | 第 2 章 |
两个 int 值相除时,结果向零截断。如果任一操作数为 float,则结果为 float。
3. 加法运算符
加法和减法运算。左结合。+ 运算符也可用于字符串拼接。
| 运算符 | 说明 | 示例 | 结果 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|---|
+ | 加法 / 字符串拼接 | 5 + 3 | 8 | 5 + 3 | 5 + 3 | 5 + 3 | 5 + 3 | 第 2 章 |
- | 减法 | 10 - 4 | 6 | 10 - 4 | 10 - 4 | 10 - 4 | 10 - 4 | 第 2 章 |
4. 比较运算符
这些运算符比较两个值并返回 bool。适用于数字、字符串(字典序)和布尔值。
| 运算符 | 说明 | 示例 | 结果 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|---|
< | 小于 | 10 < 20 | true | 10 < 20 | 10 < 20 | 10 < 20 | 10 < 20 | 第 2 章 |
> | 大于 | 10 > 20 | false | 10 > 20 | 10 > 20 | 10 > 20 | 10 > 20 | 第 2 章 |
<= | 小于等于 | 10 <= 10 | true | 10 <= 10 | 10 <= 10 | 10 <= 10 | 10 <= 10 | 第 2 章 |
>= | 大于等于 | 10 >= 20 | false | 10 >= 20 | 10 >= 20 | 10 >= 20 | 10 >= 20 | 第 2 章 |
5. 相等运算符
相等性检查和类型测试。
| 运算符 | 说明 | 示例 | 结果 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|---|
== | 等于 | 10 == 20 | false | 10 == 20 | 10 == 20 | 10 == 20 | 10 === 20 | 第 2 章 |
!= | 不等于 | 10 != 20 | true | 10 != 20 | 10 != 20 | 10 != 20 | 10 !== 20 | 第 2 章 |
is | 类型检查 / 模式匹配 | x is int | bool | matches! | isinstance() | 不适用 | typeof / instanceof | 第 7 章、第 17 章 |
is 运算符检查值是否匹配某个类型或模式。在控制流中,它会触发智能类型转换(smart cast),在分支内自动收窄类型(详见[第 17 章][ch17])。
6. 逻辑与
短路求值:如果左侧为 false,则不计算右侧。
| 运算符 | 说明 | 示例 | 结果 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|---|
&& | 逻辑与(符号形式) | true && false | false | true && false | 不适用 | a && b | a && b | 第 2 章 |
and | 逻辑与(关键字形式) | true and false | false | 不适用 | a and b | 不适用 | 不适用 | 第 2 章 |
两种形式可互换使用。a2p 转译器会将 && 转换为 Python 的 and。
7. 逻辑或
短路求值:如果左侧为 true,则不计算右侧。
| 运算符 | 说明 | 示例 | 结果 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|---|
|| | 逻辑或(符号形式) | true || false | true | true || false | 不适用 | a || b | a || b | 第 2 章 |
or | 逻辑或(关键字形式) | true or false | true | 不适用 | a or b | 不适用 | 不适用 | 第 2 章 |
两种形式可互换使用。a2p 转译器会将 \|\| 转换为 Python 的 or。
8. 空值合并
| 运算符 | 说明 | 示例 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|
?? | 为 ?T 提供默认值 | name ?? "unknown" | .unwrap_or("unknown") | name or "unknown" | 不适用 | name ?? "unknown" | 第 9 章 |
?? 运算符在左侧为 Some(value) 时返回该值,否则返回右侧作为默认值。它仅适用于 ?T(可选类型)值。
9. 范围运算符
用于 for 循环和创建范围表达式。
| 运算符 | 说明 | 示例 | 生成值 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|---|
.. | 右开区间 | 0..5 | 0, 1, 2, 3, 4 | 0..5 | range(0, 5) | for (i=0;i<5;i++) | 不适用 | 第 3 章 |
..= | 右闭区间 | 1..=5 | 1, 2, 3, 4, 5 | 1..=5 | range(1, 6) | for (i=1;i<=5;i++) | 不适用 | 第 3 章 |
.. 范围在右侧是开区间(不包含上界)。..= 范围在右侧是闭区间(包含上界)。
10. 赋值运算符
在 Auto 中,赋值是语句而非表达式。它不返回值。
| 运算符 | 说明 | 示例 | 等价写法 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|---|
= | 赋值 | x = 5 | -- | x = 5 | x = 5 | x = 5 | x = 5 | 第 2 章 |
+= | 加后赋值 | x += 3 | x = x + 3 | x += 3 | x += 3 | x += 3 | x += 3 | 第 2 章 |
-= | 减后赋值 | x -= 2 | x = x - 2 | x -= 2 | x -= 2 | x -= 2 | x -= 2 | 第 2 章 |
*= | 乘后赋值 | x *= 4 | x = x * 4 | x *= 4 | x *= 4 | x *= 4 | x *= 4 | 第 2 章 |
/= | 除后赋值 | x /= 2 | x = x / 2 | x /= 2 | x //= 2 | x /= 2 | x /= 2 | 第 2 章 |
%= | 取余后赋值 | x %= 3 | x = x % 3 | x %= 3 | x %= 3 | x %= 3 | x %= 3 | 第 2 章 |
11. 管道运算符
| 运算符 | 说明 | 示例 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|
|> | 前向管道 | data |> transform |> save | 方法链 | 方法链 | 不适用 | 方法链 | 第 19 章 |
管道运算符将左侧的值作为第一个参数传递给右侧的函数。它实现了数据流风格,转换过程从左到右阅读。这等价于方法链(data.transform().save()),但适用于独立函数。
12. 错误传播运算符
这些后缀运算符用于处理 ?T(可选类型)和 !T(结果类型)。它们具有最低优先级,因为它们作用于整个前面的表达式。
| 运算符 | 说明 | 示例 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|
后缀 ! | 解包 !T;遇 Err 时 panic | parse(s)! | .unwrap() | 不适用 | 不适用 | !(非空断言) | 第 9 章 |
后缀 ? | 传播错误 / 解包 !T | read_file(path)? | ?(相同) | 不适用 | 不适用 | 不适用 | 第 9 章 |
后缀 ! 解包 !T 值,成功时返回 Ok 中的值,失败时以 Err 消息触发 panic。类似于 Rust 的 .unwrap()。
后缀 ? 将错误沿调用栈向上传播。在返回类型标注了 ! 的函数内,expr? 在成功时解包结果,失败时将错误返回给调用者。等价于 Rust 的 ? 运算符。
类型修饰运算符
这些运算符出现在类型位置而非表达式位置,用于修改类型标注的含义。
| 修饰符 | 说明 | 示例 | Rust 等价物 | 章节 |
|---|---|---|---|---|
?T | 可选(可空)值 | fn find(id int) ?User | Option<T> | 第 9 章 |
!T | 结果(可能失败)值 | fn read(path str) !str | Result<T, String> | 第 9 章 |
~T | 异步蓝图(期约值) | fn fetch(url str) ~str | impl Future<Output=T> | 第 16 章 |
这些修饰符可以组合使用:~?String 表示未来的可选字符串,~!int 表示未来的可能失败的整数。
访问运算符
这些运算符用于成员访问和可选链式调用。它们不在优先级表中列出,因为它们是具有固有优先级的后缀访问符(从左到右,紧密结合)。
| 运算符 | 说明 | 示例 | Rust | Python | C | TypeScript | 章节 |
|---|---|---|---|---|---|---|---|
. | 字段 / 方法访问 | user.name | user.name | user.name | user.name | user.name | 第 8 章 |
?. | 可选链式访问 | addr?.city | .as_ref()?.city | 不适用 | 不适用 | addr?.city | 第 9 章 |
.await | 等待异步蓝图 | fetch().await | .await | await | 不适用 | await | 第 16 章 |
注意事项
- 短路求值:
&&和||仅在必要时才计算右侧。如果&&的左侧为false,则跳过右侧。如果\|\|的左侧为true,则跳过右侧。 - 不支持运算符重载:Auto 不支持用户自定义的运算符重载。所有运算符的语义由语言固定定义。
- 整数除法:两个
int值用/相除时向零截断。如需小数结果,至少需要一个float操作数。 - 赋值不是表达式:与 C 不同,Auto 中的赋值不返回值。不能写成
x = y = 5,也不能在if条件中使用赋值。 - 关键字别名:
and和or是&&和\|\|的别名。它们的存在主要是为了可读性,以及便于 Python 转译器直接映射。