运算符
运算符用于在程序运行时执行数学或逻辑运算
Z1h 语言内置的运算符有:
- 算术运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 赋值运算符
- 其他运算符
接下来让我们来详细看看各个运算符的介绍
算术运算符
下表列出了Z1h语言的所有算术运算符. 假定 A 值为 10, B 值为 20.
运算符 | 描述 | 示例 |
---|---|---|
+ | 相加 | A + B 输出结果 30 |
- | 相减 | A - B 输出结果 -10 |
* | 相乘 | A * B 输出结果 200 |
/ | 相除 | B / A 输出结果 2 |
% | 求余 | B % A 输出结果 0 |
++ | 自增 | A++ 输出结果 11 |
– | 自减 | A– 输出结果 9 |
** | 幂运算 | A ** B 输出10的20次方结果100000000000000000000 |
关系运算符
下表列出了Z1h语言的所有关系运算符. 假定 A 值为 10, B 值为 20.
运算符 | 描述 | 示例 |
---|---|---|
== | 检查两个值是否相等, 如果相等返回 True 否则返回 False | (A == B) 为 False |
!= | 检查两个值是否不相等, 如果不相等返回 True 否则返回 False | (A != B) 为 True |
> | 检查左边值是否大于右边值, 如果是返回 True 否则返回 False | (A > B) 为 False |
< | 检查左边值是否小于右边值, 如果是返回 True 否则返回 False | (A < B) 为 True |
>= | 检查左边值是否大于等于右边值, 如果是返回 True 否则返回 False | (A >= B) 为 False |
<= | 检查左边值是否小于等于右边值, 如果是返回 True 否则返回 False | (A <= B) 为 True |
逻辑运算符
下表列出了Z1h语言的所有逻辑运算符. 假定 A 值为 True, B 值为 False.
运算符 | 描述 | 示例 |
---|---|---|
&& | 逻辑 AND 运算符. 如果两边的操作数都是 True, 则条件 True, 否则为 False | (A && B) 为 False |
|| | 逻辑 OR 运算符. 如果左值为空值或零值(如null/0/false/"等), 则返回右值; 否则返回左值 | (A || B) 为 True |
?? | 如果左值为空值或抛出异常或包含错误类型, 则返回右值; 否则返回左值 | (A ?? B) 为 True |
! | 逻辑 NOT 运算符. 如果条件为 True, 则逻辑 NOT 条件 False, 否则为 True | !(A && B) 为 True |
?? 操作符
上述逻辑运算符中除了??
符号之外, 大多数运算符和其它语言(尤其是js)表现基本一致, 所以这里着重讲一下??
的用法
print(false ?? 123)
// false
print(0 ?? 123)
// 0
print(null ?? 456)
// 456
print(1 / 0 ?? 789)
// 左边抛出异常, 返回右值 789
recover
结合recover
函数使用??
, 可以很优雅地取代try...catch...
语法
调用recover
函数时, 传入一个函数对象, 该对象的第一个参数就是左值抛出的异常对象
print(1 / 0 ?? recover(e=>`抛出异常:${e.Error()}`))
// 抛出异常:Runtime exception at line 1, column 7: division by zero
panic(123) ?? recover(err=>print(`抛出的内容是: ${err.Origin()}`))
// 抛出的内容是: 123
位运算符
位运算符对整数在内存中的二进制位进行操作.
下表列出了位运算符 &, |, 和 ^ 的计算:
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
假定 A = 60; B = 13; 其二进制数转换为:
A = 0011 1100
B = 0000 1101
-----------------
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
支持的位运算符如下表所示. 假定 A 为60, B 为13:
运算符 | 描述 | 示例 |
---|---|---|
& | 按位与运算符"&"是双目运算符. 其功能是参与运算的两数各对应的二进位相与 | (A & B) 结果为 12, 二进制为 0000 1100 |
| | 按位或运算符"|"是双目运算符. 其功能是参与运算的两数各对应的二进位相或 | (A | B) 结果为 61, 二进制为 0011 1101 |
^ | 按位异或运算符"^"是双目运算符. 其功能是参与运算的两数各对应的二进位相异或, 当两对应的二进位相异时, 结果为1 | (A ^ B) 结果为 49, 二进制为 0011 0001 |
<< | 左移运算符"<<"是双目运算符. 左移n位就是乘以2的n次方. 其功能把"<<"左边的运算数的各二进位全部左移若干位, 由"<<"右边的数指定移动的位数, 高位丢弃, 低位补0 | A << 2 结果为 240 , 二进制为 1111 0000 |
>> | 右移运算符">>"是双目运算符. 右移n位就是除以2的n次方. 其功能是把">>"左边的运算数的各二进位全部右移若干位, ">>"右边的数指定移动的位数 | A >> 2 结果为 15 , 二进制为 0000 1111 |
赋值运算符
下表列出了Z1h语言的所有赋值运算符
运算符 | 描述 | 示例 |
---|---|---|
= | 简单的赋值运算符, 将一个表达式的值赋给一个左值 | C = A + B 将 A + B 表达式结果赋值给 C |
+= | 相加后再赋值 | C += A 等于 C = C + A |
-= | 相减后再赋值 | C -= A 等于 C = C - A |
*= | 相乘后再赋值 | C *= A 等于 C = C * A |
/= | 相除后再赋值 | C /= A 等于 C = C / A |
%= | 求余后再赋值 | C %= A 等于 C = C % A |
<<= | 左移后赋值 | C <<= 2 等于 C = C << 2 |
>>= | 右移后赋值 | C >>= 2 等于 C = C >> 2 |
&= | 按位与后赋值 | C &= 2 等于 C = C & 2 |
^= | 按位异或后赋值 | C ^= 2 等于 C = C ^ 2 |
|= | 按位或后赋值 | C |= 2 等于 C = C | 2 |
赋值语句
Z1h同时支持Java
和Python
的两种赋值语句风格, 详见变量
三元运算符
Z1h同时支持Java
和Python
的两种三元运算符风格
运算符 | 风格 | 示例 |
---|---|---|
判断语句 ? 正确时的值: 错误时的值 | Java/JavaScript | print(4 % 2 == 0? "A": "B") |
正确时的值 if 判断语句 else 错误时的值 | Python | print("AA" if 4 % 2 == 0 else "BB") |
其他运算符
下表列出了Z1h语言的其他运算符
运算符 | 描述 | 示例 |
---|---|---|
& | 返回变量存储地址 | &a将给出变量的实际地址 |
* | 指针变量 | *a是一个指针变量 |
… | 展开(spread)操作 | 有展开、复制等功能 |
?.或?[] | 可选链 | a?.b, a?[c] |
… 展开操作符
...
的用处有9种:
- 作为函数形参时, 右结合表示聚合一部分形参为数组
- 作为函数形参时, 左结合表示将该参数复制一份作为实参
- 作为函数形参时, 左+右结合表示完全展开该参数到本作用于本作用域
- 调用函数时, 使用左结合表示先复制再传入函数
- 调用函数时, 使用右结合表示将该实参展开
- 从列表中提取变量时, 左结合表示从列表中取出之后复制再赋值
- 从列表中提取变量时, 右结合表示聚合列表的部分切片
- 从列表中提取变量时, 左+右结合表示将对应的值的键值对展开到当前变量环境
- 从对象中提取变量时, 左结合表示获取到对象字段后复制再赋值
以下为示例代码
作为函数形参时, 右结合表示聚合一部分形参为数组
f = (name, friends...) => print(`My name is ${name}, I have ${friends.len} friends, they are ${friends.join(' and ')}!`)
f('zwr', 'aaa', 'bbb', 'ccc')
作为函数形参时, 左结合表示将该参数复制一份作为实参
// 你可以运行一遍后, 将...e的...去掉再试试
f = (...e) => {
e.name = 'zwr'
print('In function:', e)
}
people = {name: 'zq', age: 25}
f(people)
print('Out function:', people)
作为函数形参时, 左+右结合表示完全展开该参数到本作用于本作用域
f = (...e...) => print(`My name is ${name}, age is ${age}`)
f({
name: 'zwr',
age: 26,
})
调用函数时, 使用左结合表示先复制再传入函数
f = e=>{e.Method='POST'}
req = new(net_http.Request)
req.Method = 'GET'
f(...req)
print(req.Method)
调用函数时, 使用右结合表示将该实参展开
path.Join('aaa', ['bbb', 'ccc']..., 'ddd', ['eee', 'fff']...)
从列表中提取变量时, 左结合表示从列表中取出之后复制再赋值
a = [{name: 'zwr', age: 26}, {name: 'zq', age: 25}];
[zwr, ...zq] = a;
zq.age++
print('Out:', zq)
print('In:', a[1])
从列表中提取变量时, 右结合表示聚合列表的部分切片
a = [1, 2, 3, 4];
[top, other..., bottom] = a;
print('Top:', top)
print('Other:', other)
print('Bottom:', bottom)
从列表中提取变量时, 左+右结合表示将对应的值的键值对展开到当前变量环境
请注意, 如果你不能确认展开的结构, 请慎用该特性, 以免污染当前变量环境
n = {name: 'zwr', age: 26};
[...a..., b...] = [n, n, n];
print('a =', a, '; b =', b)
print(`name = ${name}, age = ${age}`)
从对象中提取变量时, 左结合表示获取到对象字段后复制再赋值
n = {name: 'zwr', wife: {name: 'zq', age: 25}};
{name, ...wife} = n
wife.age++
print('Out:', wife)
print('Origin:', n)
可选链
尝试对map、数组、任意对象进行取值时, 由于字段不存在或索引超出了边界, 会抛出各种异常, 此时可以用可选链来试探取值
可选链是短路的, 和||、&&、??类似, 当左值为nil时, 不会调用右值
me = {name: 'zwr'}
print(
'School name: %v, alias :%v'.fmt(
me?.school?['name'],
me?.school?.alias?[1]
)
)
me.school = {
name: 'SCUT',
alias: ['五山禅寺', '华南鲤工大学']
}
print(
'School name: %v, alias :%v'.fmt(
me?.school?['name'],
me?.school?.alias?[1]
)
)
运算符优先级
有些运算符拥有较高的优先级, 二元运算符的运算方向均是从左至右. 下表列出了所有运算符以及它们的优先级, 由上至下代表优先级由高到低
优先级 | 运算类型 | 关联性 | 运算符 |
---|---|---|---|
20 | 圆括号 | 不相关 | ( … ) |
19 | 成员访问 | 从左到右 | … . … |
需计算的成员访问 | 从左到右 | … [ … ] | |
new (带参数列表) | n/a | new … ( … ) | |
函数调用 | 从左到右 | … ( … ) | |
可选链(Optional chaining) | 从左到右 | ?. | |
18 | new(无参数列表) | 从右到左 | new … |
17 | 后置递增(运算符在后) | … ++ | |
后置递减(运算符在后) | … - - | ||
16 | 逻辑非 | 从右到左 | ! … |
按位非 | ~ … | ||
一元加法 | + … | ||
一元减法 | - … | ||
前置递增 | ++ … | ||
前置递减 | – … | ||
typeof | typeof … | ||
void | void … | ||
delete | delete … | ||
await | await … | ||
15 | 幂 | 从右到左 | … ** … |
14 | 乘法 | 从左到右 | |
… * … | |||
除法 | … / … | ||
取模 | … % … | ||
13 | 加法 | 从左到右 | |
… + … | |||
减法 | … - … | ||
12 | 按位左移 | 从左到右 | … << … |
按位右移 | … >> … | ||
无符号右移 | … >>> … | ||
11 | 小于 | 从左到右 | … < … |
小于等于 | … <= … | ||
大于 | … > … | ||
大于等于 | … >= … | ||
in | … in … | ||
instanceof | … instanceof … | ||
10 | 等号 | 从左到右 | |
… == … | |||
非等号 | … != … | ||
全等号 | … === … | ||
非全等号 | … !== … | ||
9 | 按位与 | 从左到右 | … & … |
8 | 按位异或 | 从左到右 | … ^ … |
7 | 按位或 | 从左到右 | … |
6 | 逻辑与 | 从左到右 | … && … |
5 | 逻辑或 | 从左到右 | … |
4 | 条件运算符 | 从右到左 | … ? … : … |
3 | 赋值 | 从右到左 | … = … |
… += … | |||
… -= … | |||
… *= … | |||
… /= … | |||
… %= … | |||
… <<= … | |||
… >>= … | |||
… >>>= … | |||
… &= … | |||
… ^= … | |||
… | = … | ||
2 | yield | 从右到左 | yield … |
yield* | yield* … | ||
1 | 展开运算符 | n/a | … … |
0 | 逗号 | 从左到右 | … , … |