跳过正文
  1. Lumesh 文档/
  2. 语法/

语法:运算符

2316 字·5 分钟
目录

基础语法:算术运算、逻辑运算、自定义运算

二、运算符
#

1. 运算符分类与优先级
#

优先级从高到低(数值越大优先级越高)

优先级运算符/结构示例/说明
13括号 ()(a + b) * c
12单目运算符 !-, __..!flag-5
11幂运算 ^2 ^ 3
10乘除模 */%, _*..a * b % c
9加减 +- ,_+..a + b - c
8比较 ==!=>a >= b
7逻辑与 &&cond1 && cond2
6逻辑或 ||cond1 || cond2
5条件运算符 ? :cond ? t : f
4Lambda 表达式 ->x -> x+1
3错误处理 ?: ?.3 / 0 ?: 1
2管道 |ls -1 | sort
2重定向 << >> >!date _ >> /tmp/day.txt
1赋值 =:= ?x = 5let y := 10

管道和重定向同级,逻辑运算比管道和重定向优先级更高。

2. 空格规则
#

运算符类型是否需要空格示例
常规运算符两侧应空格a + b, x <= 10
非严格模式,部分符号两侧可以不空格a+b, x<=10, a=5
-/应空格b-3为字符串,3- b为减法
自定义运算符必须用下划线开头且两侧空格x _*+ y, a _?= b
后缀运算符,必须用双下划线开头且空格x __*+
前缀运算符前面为空格或开始,后面无空格!x, -7
中缀运算符前后均无空格dict.key, 1..9
后缀运算符前后均无空格func(a), array[i], 10M

自定义操作符

  • 自定义操作符是以 _开头的符号,只能包含符号,不能包含数字或字母。

  • 自定义单目运算符 以 __开头,如__+, 优先级同单目运算符。仅能用于后缀运算。

  • 自定义+级运算符 以 _+开头,如_+%,优先级同+ -

  • 自定义*级运算符 以 _*开头,如_*-,优先级同* /

    1let __++ = x -> x + 1;
    23 __++

3. 特别的操作符
#

  • == != 带类型相等比较.

  • ~= !~= 值相等比较.

  • ~: !~: 是否包含(可用于字符串,数组,区间,字典(检测是否包含指定key). 支持正则包含检测。

举例:

15 == "5"        # False
25 ~= "5"        # True
3"abc" ~: "a"    # True
40..<8 ~: 8      # False
50..8 ~: 8       # True
6"abc" ~: '\d'   # False

4. 四则运算
#

+ - * / 是已经重载的运算符 除了可以完成数字的四则运算外,还可以完成更复杂的运算 % ^ 仍为普通运算,只支持数字之间的运算。

加法 +
#

数字

  • 数字 + 数字 = 数字以高精度相加

    11 + 2.5           # → 3.5
  • 数字 + 字符串 = 以数值相加

    11 + "2.5"           # → 3.5
  • 数字 + 列表 = 一起求和

    11 + [2.5,3]           # → 6.5

字符串

  • 字符串 + 字符串 = 字符串连接

    1"1" + 2.5           # → "12.5"
  • 字符串 + 列表 = 一起串联

    1"1" + [2,3]           # → "123"

区间

  • 区间 + 整数 = 区间扩充(正数从尾部,负数从头部)
    10..8 + 2           # → 0..10
    20..8 + (-2)           # → 2..8

列表

  • 列表 + 列表 = 列表合并

    1[1,2] + [3,4,5]           # → [1,2,3,4,5]
  • 列表 + 其他 = 向列表插入值

    1[1] + 2.5           # → [1,2.5]

映射

  • 映射 + 映射 = 映射合并

    1{a:b} + {c:d}           # → {a:b,c:d}
  • 映射 + 其他 = 向映射插入值

    1{a:b} + c           # → {a:b,c:c}

字节

  • 字节 + 字节 = 字节追加
  • 字节 + 字符串 = 字节追加

其他情况抛出异常


减法 -
#

数字

  • 数字 - 数字 = 数字以高精度相减

    11 - 2.5           # → -1.5
  • 数字 - 字符串 = 以数值相减

    11 - "2.5"           # → -1.5

字符串

  • 字符串 - 字符串 = 字符串移除(首次出现)

    1"i am lume" - "a"           # → "i m lume"
  • 字符串 - 浮点数 = 字符串移除(首次出现)

    1"i am lume v4.2" - 4.2           # → "i am lume v"
  • 字符串 - 整数 = 字符串移除(正数从尾部,负数从头部)

    1"98101" - 1           # → "9801"
    2"98101" - (-2)           # → "101"

超出长度则返回空字符串

区间

  • 区间 - 整数 = 区间缩放(正数从尾部,负数从头部)
    10..8 - 2           # → 0..6
    20..8 - (-2)           # → -2..8

列表

  • 列表 - 列表 = 列表差集

    1[1,2,3,4,5] - [3,4,5]           # → [1,2]
  • 列表 - 其他 = 列表移除

    1[1,2,3] - 2           # → [1,3]

映射

  • 映射 - 映射 = 映射差集

    1{a:b,c:d} - {c:d}           # → {a:b}
  • 映射 - 其他 = 映射键移除

    1{a:b,c:d} - c           # → {a:b}

其他情况抛出异常


乘法 *
#

数字

  • 数字 * 数字 = 数字相乘
    12 * 2.5           # → 5
  • 数字 * 字符串 = 以数值相乘
    12 * "2.5"           # → 5

字符串

  • 字符串 * 整数 = 字符串重复

    1"2" * 5           # → "22222"
  • 列表 * 列表 = 矩阵乘法

    1[[1,2,3],[4,5,6]] * [[7,8],[9,10],[11,12]]
    2
    3# → 返回
    4    +----------+
    5    | C0   C1  |
    6    +==========+
    7    | 58   64  |
    8    | 139  154 |
    9    +----------+

矩阵乘法要求维度正确 如内部有缺失元素,计算时会以0填充

  • 列表 * 数字 = 每个元素乘法
    1[1,2,3] * 2.5           # → [2.5,5,7.5]

除法 /
#

数字

  • 数字 / 数字 = 数字相除
    15 / 2             # → 2
    25 / 2.0           # → 2.5
  • 数字 / 字符串 = 以数值相除
    15 / "2"               # → 2
    25.0 / "2.5"           # → 2

列表

  • 列表 / 数字 = 每个元素除法
    1[2,4,6] / 2          # → [1,2,3]

5. 隐式类型转换
#

数字之间的运算,自动向高精度类型转换。 不同类型数据相加,总是尝试自动转为第一个数据的类型。

1# 非严格模式
23 + "5"                        # → 8(自动转为整数)
3"10" + 2                       # → "102"  (自动转为字符串)
4"10" * 2                       # → "1010"  (字符串重复)
5[1,2,3] + 5                    # → [1,2,3,5]
6[2,3] - 2                      # → [3]
70..8 + 3                       # → 0..11
8{name:wang, age:18} - name     # → {age:18}

6. 增量运算符
#

+= -= *= /= 只适用于数字运算。

对于未初始化的,自动初始化为0

和四则运算不同的是,对于非数字会返回None,而不是抛出异常。 如:

1a += 1               # → 1
2a += [1]             # None

边缘情况

  • 除以零会报错。

7. 逻辑运算符
#

&& || 返回Bool值 他们会把左右两侧的值转为Bool值并进行逻辑运算。如:

1False && print a   # 不执行打印,返回False
2True && print a   # 执行打印,返回False,因为右侧语句返回None
  • 与Bash比较 逻辑运算符不同于Bash,而是与其他编程语言中的含义相同,只是进行纯粹的逻辑运算。

    • 在Bash中,&& 表示左侧执行成功才执行右侧,不返回值。
    • 在Lumesh中,&& 表示左侧返回True才计算右侧,始终返回布尔值。 类似的,
    • 在Bash中,|| 表示左侧执行失败才执行右侧,不返回值。
    • 在Lumesh中,|| 表示左侧返回False才计算右侧,始终返回布尔值。

要实现类似Bash中的效果,可以:

  • 左侧执行成功才执行右侧: left_arm ; right_arm
  • 左侧执行失败才执行右侧: left_arm ?: right_arm

8. 选择运算符
#

test ? t : f

等同于 if test { t } else { f}

支持嵌套,如test?t:b?tb:fb


三、自定义运算符
#

自定义单目运算符
#

自定义单目运算符必须以__开头,定义后,作为后缀运算符使用。

1# 定义
2let __! = x -> Math.sum(x)
3# 使用
4[5,6,7]  __!              # 18

为何不定义前置运算符? 因为和函数调用方式类似,还不如直接定义函数。 如果您认为有使用的必要,可以到项目主页提交请求。

自定义双目运算符
#

自定义单目运算符必须以_开头(但不以__开头),定义后,作为双目运算符使用。

1# 定义自定义运算符
2let _+ = (a, b) -> a.concat(b)  # 自定义加法
3
4# 使用自定义运算符
5[1, 2] _+ [3, 4]    # [1, 2, 3, 4]

双目运算符涉及到运算优先级。

  • _+开头的,优先级同加法。
  • _*开头的,优先级同乘法。
  • _开头的其他运算符,优先级高于幂运算,低于单目运算(如!)。

相关文章