函数、命令
六、函数#
fn函数定义#
- 使用
fn定义,支持默认参数,支持剩余参数收集。1fn add(a,b,c=10,*d) { 2 return a + b + c + len(c) 3} 4 5# 等价于: 6fn add(a,b,c=10,*d) { 7 a + b + c + len(c) 8} 9 10echo add(2, 3) # 输出 5 11echo add(2,3,4, 5) # 输出 10
lambda表达式#
使用
->定义。1let add = (x,y) -> x + ylambda 与 普通函数的区别:
- lambda 不支持默认参数和return语句,不支持剩余参数收集。
- lambda 支持部分参数应用,返回后续lambda
相同的是: lambda和函数都 继承当前环境变量,在隔离的环境中运行,不会污染当前环境。
函数调用#
函数名后紧跟()或! 执行函数。
1# 自定义函数可以这样调用
2add(3,5)
3# 或者这样
4add! 3 5 #注意需要添加!后缀,用以区别于命令调用。区分函数调用和执行命令的方式,有助于避免同名函数覆盖命令,如:
1# 测试用例6:函数与命令同名覆盖
2fn ls() { echo "My ls" }
3ls -l # 执行系统命令ls
4ls() # 调用函数
5ls! # 使用!后缀时,调用函数,这是一个将括号扁平化的语法糖。Tips:
- 当参数是字面的lambda表达式时,请使用括号模式,平铺模式无法解析。
- 类似的,当参数是字母的&&等逻辑运算时,请使用括号模式,或使用括号分组后的平铺模式。
边缘情况:
- 函数名冲突时,新定义会覆盖旧的。
- 调用函数时,参数数量不匹配会报错。如:
[ERROR] arguments mismatch for functionadd: expected 3, found 1
链式调用#
1[1,3,5,6].sum()
2
3"hello world"
4 .split(' ')
5 .map(s -> s.to_upper())
6 .join('-')
7 .green()对于常用数据类型,可以直接使用链式调用,包括:
String, List, Map, Time, Integer, Float, Range
装饰器#
装饰器是一种特殊的高阶函数,可以在特定函数的执行前后,插入需要的逻辑。
1# 在函数定义时使用装饰器
2@timeit
3fn test(n){
4 for i in 0..n {
5 n += i
6 }
7 print 'sum is' n
8}
9
10# decorator func
11fn timeit(){
12 fn wrapper(func_t){
13 (args_t) -> {
14 let start = Time.stamp_ms() # 函数执行前的逻辑
15 func_t(args_t) # 函数执行
16 let end = Time.stamp_ms() # 函数执行后的逻辑
17 print '>Time:'.green().bold() (end - start) 'ms'
18 }
19 }
20}请注意
- 同一个函数上应用的所有装饰器定义的变量,不能重名。
例如,要在上面的
test函数上应用第二个装饰器,则该装饰器不能再使用func_t,args_t变量名。 这是综合考虑性能和便捷性的权衡,为了更高的性能,我们决定接受这个小小的不便。
七、运行系统命令#
命令调用#
在lumesh中,您可以像在其他shell中一样,便捷的运行程序,如
1ls
2ls -l多条命令,前面的命令失败则后续的命令不会继续执行;
除非错误已经处理:
1ls '/0' ; ls -l # 后者不会执行 2ls '/0' ?. ; ls -l # 后者会执行使用
^后缀强制开启命令模式1let id = 5 2id^ -u # 告诉系统这个是命令空参数命令
1notepad.exe # 如果没有被识别为命令(比如Windows下,带扩展名的命令) 2notepad.exe _ # 传入空参数,强制识别为命令
通配符扩展#
在lumesh中,同样支持~ 目录扩展和*扩展:
1ls ~/**/*.md但不支持bash中的{}扩展
后台运行 和 输出控制符#
和bash一样,使用
&符号让程序后台运行。输出控制符
&:我们采用更简洁的方式关闭命令的输出。输出控制符仅适用于命令,不适用于函数。
1thunar & # run in background, and shutdown stdout and stderr 2ls &- # shutdown stdout 3ls /o &? # shtudown stderr 4ls /o '/' &+ # shutdown stdout and stderr 5 6ls /o '/' &? | bat # shutdown stderr and pipe stdout to next cmd.
下面是和bash的语法对比:
| 任务 | lumesh | bash |
|---|---|---|
| 后台运行 | cmd & | cmd & |
| 关闭标准输出 | cmd &- | cmd 1> /dev/null |
| 关闭错误输出 | cmd &? | cmd 2> /dev/null |
| 关闭所有输出 | cmd &. | cmd 2>&1 > /dev/null |
| 输出错误到标准* | cmd &+ | cmd 2>&1 |
输出通道#
标准输出 (定义和bash一样,可以用
&-关闭标准输出)错误输出 (定义和bash一样,可以用
&?关闭标准输出,可以用错误处置符处理错误)结构化数据通道 (lumesh特有,可以在配置中关闭)
在配置文件中设置
let LUME_PRINT_DIRECT= False可关闭结构化数据通道1❯ ls 2Documents Downloads dprint.json typescript # 标准输出 3 4 5❯ ls /x 6ls: cannot access '/x': No such file or directory # 错误输出 7[ERROR] command `ls` failed: "exit status: 2" # Lumesh错误捕获,错误处置符处理的目标 8 9❯ 3 + 5 108 # 标准输出 11 >> [Integer] << # 结构化通道 数据类型提示 128 # 结构化通道(运算结果)
输出打印
print 消费掉运算结果,打印到标准输出
tap 打印到标准输出,但同时保留运算结果
1❯ print 3+5 28 3 4❯ tap 3+5 58 6 7 >> [Integer] << 88
八、内置函数库#
Lumesh内置大量实用的函数库, 以实现便捷的函数式编程,如
- 集合操作:
List.reduce, List.map - 文件系统:
Fs.ls, Fs.read, Fs.write - 字符串处理:
String.split, String.join、正则模块、格式化模块 - 时间操作:
Fs.now, Fs.format - 数据转换: Into模块,From模块
- 数学计算: 完整的数学函数库
- 日志记录: Log模块
- UI操作:
Ui.pick, Ui.confirm
可通过 help 命令查看可用模块和函数。
可通过 help String 命令查看具体模块的函数。
内置函数支持三种调用方式
1String.red(msg)
2String.red msg
3String.red! msg以及链式调用和管道方法调用:
1msg.red()
2msg | .red()详细内容,请继续阅读: