操作员
几乎所有合约都对数据进行操作:将某些值转换成另一个值。 范围可能各不相同,但运营商是此类修改的核心。
本页按照[优先级](#precedence)的递减顺序列出了 Tact 中的所有运算符,并附有使用示例。
操作员表
下表列出了按 优先级:从高到低递减的运算符。
简要说明 | 操作员 |
---|---|
括号 | () |
一元后缀 | !! |
一元前缀 | [+ ][正] [- ][负] [! ][负] [~ ][b-not]。 |
乘法 | [* ][mul] [/ ][div] [% ][mod]。 |
添加剂 | [+ ][加] [- ][分] |
轮班 | [>> ][shr] << 。 |
关系 | > >= < [<= ][le]。 |
平等 | [== ][eq] [!= ][eq]。 |
位与 | [& ][b-and]。 |
比特 XOR | ^ 。 |
位操作 OR | [| ][b-or]。 |
逻辑与 | [&& ][l-and]。 |
逻辑或 | [|| ][l-or] |
三元 | ?: |
任务 | [= ][赋值] 和 所有增强赋值运算符 |
优先级
本页所有运算符的优先级从高到低依次递减。 优先级用于选择在特定情况下考虑哪个运算符。 每当出现模棱两可的情况时,Tact 会优先选择优先级较高的运算符,而不是优先级较低的运算符。
例如,减号 (-
) 可被视为减法运算符或否定运算符,它将表达式的正负符号颠倒过来,反之亦然。 由于在两者有歧义的情况下,后者的优先级高于前者,Tact 将首先把 -
视为否定操作符。 如果这对给定表达式没有意义,它才会将其视为减法运算符。
请看下面的代码
尽管这个例子可能很简单,但忽略优先级规则往往会导致运算符出现混乱的情况。 由于括号在所有表达式和运算符中具有最高优先级,因此用括号封装每个操作可以确保正确的操作顺序。
括号,()
括号(也可称为圆括号,()
)与其说是实际的运算符,不如说是一种标点符号,但其[优先级](#优先级)高于任何其他运算符的优先级。 使用括号可覆盖运算顺序:
一元
这里的”一元”是指只应用于给定表达式的一个操作数。除了非空断言,所有一元运算符都具有相同的优先级。
一元运算符可以是两种类型之一:
- 前缀 - 放在表达式之前。
- 后缀(或后缀) - 放在表达式之后。
非空断言,!!
一元双叹号(非空断言)运算符 !
是一个后缀运算符,它强制执行非null
值,如果可选变量不是null
,则允许直接访问可选变量的值。 否则,如果编译器可以跟踪,则引发编译错误;如果不能跟踪,则抛出退出代码 128异常:空引用异常”。 可应用于任何可选变量,无论其类型是非空
。
加号,+
虽然 Tact 编译器的语法中指定了一元加号运算符 +
,但它只作为 [二元运算符](#binary-add)存在。
否定,-
一元减号(negation)运算符 -
是一个前缀运算符,用于反转表达式的符号。 只能应用于 Int
类型的值:
逆,!
一元感叹号(inversion)运算符 !
是一个前缀运算符,用于反转表达式的布尔值——将 true
变为 false
,反之亦然。只能应用于 Bool
类型的值:
双向 NOT, ~
单引号 tilde(bitwise not)运算符 ~
是一个前缀运算符,它将表达式二进制表示中的每一位反转或_flip_,即把 改为 ,反之亦然。 只能应用于 Int
类型的值:
二进制
二进制运算符按优先级递减的顺序分成几个小节。 每个小节中的操作符与小节本身具有相同的 优先级。
乘法
乘、除或求余数。
乘法,*
二进制星号 (multiplication) 运算符 *
用于两个值的乘法运算。 可能导致 整数溢出。
只能应用于 Int
类型的值:
除法,/
二进制斜线 (division) 运算符 /
用于两个值的整除,如果结果为正,则向零截断,如果结果为负,则从零截断。这也叫向下舍入(或向 舍入)。
如果尝试除以零,则会出现退出代码 4错误:整数溢出。
只能应用于 Int
类型的值:
Modulo, %
二进制百分号 (modulo) 运算符 %
用于获取整数除法的模数,不能与获取余数混淆。 对于符号相同的两个值,模运算和余运算是等价的,但当操作数的符号不同时,模运算的结果总是与_除数_(右边的值)的符号相同,而余运算的结果与_除数_(左边的值)的符号相同,这可能使它们相差一个单位的_除数_。
只能应用于 Int
类型的值:
避免两者混淆的最简单方法是通过 abs(x: Int)
优先使用正值:
加法
加法或减法。
添加,+
二进制加法运算符 +
用于将数字相加。 超出 Int
的最大值将导致退出代码 4错误:整数溢出”。
只能应用于 Int
类型的值:
减去,-
二进制减号(subtraction)运算符 -
用于将数字相减。 超出 Int
的最小值将导致退出代码 4错误:整数溢出。
只能应用于 Int
类型的值:
位移
向左或向右移动位。
右移,>>
二进制双大于号(位向右移动)运算符 >>
返回一个整数,其二进制表示为左操作数的值向右移动了右操作数的位数。向右移位的多余位被丢弃,最左边位的副本从左边移入。这种操作也称为”符号向右移动”或”算术向右移动”,因为结果数字的符号与左操作数的符号相同。这是一种更有效的方法,即用 除以左操作数,其中 等于右操作数。
只能应用于 Int
类型的值:
左移,<<
二进制双小于号(bitwise shift left)运算符 <<
返回一个整数,其二进制表示为左操作数的值向左移动右操作数的位数。向左移位的多余比特被丢弃,零比特从右边移入。这是一种更有效的方法,可以将左操作数乘以 ,其中 等于右操作数。超出 Int
的最大值将导致退出代码 4错误:整数溢出。
只能应用于 Int
类型的值:
关系
查找更大、更小或相等的数值。
大于,>
二进制_大于_运算符 >
如果左操作数大于右操作数,则返回 true
,否则返回 false
。 只能应用于 Int
类型的值:
大于或等于,>=
二进制_大于或等于_运算符 >=
如果左操作数大于或等于右操作数,则返回 true
,否则返回 false
。 只能应用于 Int
类型的值:
小于,<
二进制 less than 运算符 <
如果左操作数小于右操作数,则返回 true
,否则返回 false
。 只能应用于 Int
类型的值:
小于或等于,<=
二进制_小于或等于_运算符 <=
如果左操作数小于或等于右操作数,则返回 true
,否则返回 false
。 只能应用于 Int
类型的值:
平等与不平等,===``!=
二进制相等(equal)运算符 ==
检查其两个操作数是否_equal_,返回结果类型 Bool
。
二元不等式(not equal)运算符 !=
检查其两个操作数是否_not equal_,返回一个 Bool
类型的结果。
除了 [Cell
][cell]和 [Slice
][slice]类型会通过哈希值进行隐式比较外,这两种操作符都要求操作数为相同类型,并且都不执行隐式类型转换。
这两种运算符都可以应用于下列类型和值:
比特 AND, &
二进制安培(比特 AND)运算符 &
应用比特 AND,对操作数的每一对相应比特执行逻辑 AND运算。 当我们要清除一个数字的选定位时,这一点非常有用,因为每个位都代表一个单独的标志或布尔状态,这使得每个整数可以 “存储 “多达 个布尔值,因为 Tact 中的所有整数都是 - 位有符号的。
只能应用于 Int
类型的值:
比特 XOR, ^
二进制符串(位向 XOR)运算符 ^
应用 位向 XOR,对操作数的每一对相应位执行 逻辑排他 OR运算。 如果只有一个位是 ,则每个位置的结果都是 ,但如果两个位都是 或两个位都是 ,则结果都是 。 在这种情况下,它会对两个比特进行比较,如果两个比特不同,则给出 ;如果两个比特相同,则给出 。
它适用于将操作数的选定位反转(也称为切换或翻转),因为任何位都可以通过与 进行 “XOR “来切换。
只能应用于 Int
类型的值:
位wise OR, |
二进制条形 (bitwise OR) 运算符 |
应用 bitwise OR,对操作数的每一对相应位执行 logical OR 运算。 当我们要应用特定的 bitmask 时,这很有用。
例如,bitwise OR 通常用于 Tact 中的将基本模式与可选标记结合,方法是将特定位屏蔽到 ,以构建目标信息模式
。
只能应用于 Int
类型的值:
逻辑 AND, &&
二进制逻辑 AND(逻辑连接)运算符 &&
如果两个操作数都是 true
,则返回 true
,否则返回 false
。 它是短路的,也就是说,如果左操作数是 false
,它会立即将整个表达式求值为 false
,而不求值右操作数。
只能应用于 Bool
类型的值:
逻辑 OR, ||
二元逻辑 OR(逻辑析取)运算符 ||
只有当两个操作数都是 false
时,才返回 false
,否则返回 true
。 它是短路的,也就是说,如果左操作数是 true
,它会立即将整个表达式评估为 true
,而不评估右操作数。
只能应用于 Bool
类型的值:
三元,?:
条件(ternary)运算符是唯一一个包含三个操作数的 Tact 运算符:一个条件,后面跟一个问号(?
),然后是如果条件被评估为true
时要执行的表达式,后面跟一个冒号(:
),最后是如果条件被评估为false
时要执行的表达式。 该运算符常用于替代 if...else
语句。
条件必须解析为 [布尔
][布尔] 类型:
三元运算符是除[赋值相关运算符](#赋值)外唯一具有右关联性的运算符。 这意味着,在模棱两可的情况下,Tact 会优先选择最长的匹配序列。 简而言之,这使得三元运算符的无括号嵌套成为可能,但仅限于替代情况(冒号 :
后面的部分):
赋值,=
赋值操作符 =
用于为变量或 Message 或 Struct 的属性赋值。 赋值是一个语句,不返回值。
增强赋值运算符
增强(或复合)赋值运算符,如 +=
,将操作与 [赋值](#assignment)结合起来。 增强赋值是一个语句,不返回值。
扩充赋值在语义上等同于常规赋值,只是多了一个操作:
增强赋值运算符列表:
+=
,使用 加法运算符+
。 只能应用于Int
类型的值。-=
,使用 减法运算符-
。 只能应用于Int
类型的值。*=
,使用 乘法运算符*
。 只能应用于Int
类型的值。/=
,使用 除法运算符/
。 只能应用于Int
类型的值。%=
,使用 modulo 运算符%
。 只能应用于Int
类型的值。&=
,使用 bitwise AND 运算符&
。 只能应用于Int
类型的值。^=
,它使用 bitwise XOR 运算符^
。 只能应用于Int
类型的值。|=
,它使用 bitwise OR 运算符|
。 只能应用于Int
类型的值。