运算符

运算符用于在程序运行时执行数学或逻辑运算 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)表现基本一致, 所以这里着重讲一下??的用法 z1h print(false ?? 123) // false print(0 ?? 123) // 0 print(null ?? 456) // 456 print(1 / 0 ?? 789) // 左边抛出异常, 返回右值 789

recover

结合recover函数使用??, 可以很优雅地取代try...catch...语法 调用recover函数时, 传入一个函数对象, 该对象的第一个参数就是左值抛出的异常对象 z1h 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同时支持JavaPython的两种赋值语句风格, 详见变量

三元运算符

Z1h同时支持JavaPython的两种三元运算符风格 |运算符|风格|示例| |:-:|:-:|:-:| 判断语句 ? 正确时的值: 错误时的值|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种: 1. 作为函数形参时, 右结合表示聚合一部分形参为数组 2. 作为函数形参时, 左结合表示将该参数复制一份作为实参 3. 作为函数形参时, 左+右结合表示完全展开该参数到本作用于本作用域 4. 调用函数时, 使用左结合表示先复制再传入函数 5. 调用函数时, 使用右结合表示将该实参展开 6. 从列表中提取变量时, 左结合表示从列表中取出之后复制再赋值 7. 从列表中提取变量时, 右结合表示聚合列表的部分切片 8. 从列表中提取变量时, 左+右结合表示将对应的值的键值对展开到当前变量环境 9. 从对象中提取变量时, 左结合表示获取到对象字段后复制再赋值 以下为示例代码 作为函数形参时, 右结合表示聚合一部分形参为数组 z1h f = (name, friends...) => print(`My name is ${name}, I have ${friends.len} friends, they are ${friends.join(' and ')}!`) f('zwr', 'aaa', 'bbb', 'ccc') 作为函数形参时, 左结合表示将该参数复制一份作为实参 z1h // 你可以运行一遍后, 将...e的...去掉再试试 f = (...e) => { e.name = 'zwr' print('In function:', e) } people = {name: 'zq', age: 25} f(people) print('Out function:', people) 作为函数形参时, 左+右结合表示完全展开该参数到本作用于本作用域 z1h f = (...e...) => print(`My name is ${name}, age is ${age}`) f({ name: 'zwr', age: 26, }) 调用函数时, 使用左结合表示先复制再传入函数 z1h f = e=>{e.Method='POST'} req = new(net_http.Request) req.Method = 'GET' f(...req) print(req.Method) 调用函数时, 使用右结合表示将该实参展开 z1h path.Join('aaa', ['bbb', 'ccc']..., 'ddd', ['eee', 'fff']...) 从列表中提取变量时, 左结合表示从列表中取出之后复制再赋值 z1h a = [{name: 'zwr', age: 26}, {name: 'zq', age: 25}]; [zwr, ...zq] = a; zq.age++ print('Out:', zq) print('In:', a[1]) 从列表中提取变量时, 右结合表示聚合列表的部分切片 z1h a = [1, 2, 3, 4]; [top, other..., bottom] = a; print('Top:', top) print('Other:', other) print('Bottom:', bottom) 从列表中提取变量时, 左+右结合表示将对应的值的键值对展开到当前变量环境 请注意, 如果你不能确认展开的结构, 请慎用该特性, 以免污染当前变量环境 z1h n = {name: 'zwr', age: 26}; [...a..., b...] = [n, n, n]; print('a =', a, '; b =', b) print(`name = ${name}, age = ${age}`) 从对象中提取变量时, 左结合表示获取到对象字段后复制再赋值 z1h n = {name: 'zwr', wife: {name: 'zq', age: 25}}; {name, ...wife} = n wife.age++ print('Out:', wife) print('Origin:', n)

可选链

尝试对map、数组、任意对象进行取值时, 由于字段不存在或索引超出了边界, 会抛出各种异常, 此时可以用可选链来试探取值 可选链是短路的, 和||、&&、??类似, 当左值为nil时, 不会调用右值 z1h 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|逗号|从左到右|… , …|