变量与作用域
在值的位置,裸词表示文本:123、true、false 和 nil 都没有特殊的字面量含义。
双引号字符串支持 $name 和 $(...) 插值,以及 \"、\\、\n、\r、\t 和 \$ 转义。
单引号字符串完全保留原文,不插值也不处理转义。${name} 保持为普通文本。
三引号保留换行和缩进:"""...""" 支持相同的插值与转义,'''...''' 完全保留原文。
读取变量值时使用 $name;绑定和赋值目标使用裸名字,包括函数参数、循环绑定和环境变量设置。
变量名以字母或 _ 开头,后续可包含字母、数字和 _。绑定目标不接受引号字符串或表达式。
有类型的标量使用 #1、#1.0、#true、#false、#nil。动态文本转换使用 int、float、bool,见字面值语法与转换接口。
所有普通数据采用值语义。读取变量、赋值和函数传参都会复制值,包括列表、映射及其嵌套内容。
集合更新返回新值,使用 set 显式赋回才会更新已有变量。
(let name "a friend")(echo hello $name)(set name world)(echo "hello, $name")(export EDITOR vim)let、set 和普通命令都写在括号表达式中;每个括号表达式都会创建一个新的词法作用域。let 是声明形式,
它把名字绑定到当前括号表达式的外围作用域。同一作用域已有该名字时会报错,并且在求值右值之前检查;
嵌套作用域可以遮蔽外层绑定。顶层 (let name value) 因此会把名字绑定到会话作用域,
do、函数和循环体中的 let 则留在对应的外围作用域。
let 和 set 成功后都返回 nil;set 会先检查最近的已有绑定或已有的环境变量,名称未定义时在求值右值前报错,
然后才求值右值并更新绑定。查找不到局部变量时,会继续查找继承的环境变量。
export 为后续子进程设置环境变量,并更新已有的同名局部绑定。
环境变量与工作目录的修改属于当前 parsh 会话。
get 恰好接受一个文本变量名,参数也可以来自表达式;它按 $name 的相同规则查找并返回原始值:
(get name)(get (str na me))(echo "hello, $(get name)_friend")名称必须符合上面的变量命名规则,未定义时会报错。
get 保留列表、映射、数值、布尔值及 nil 的原始类型,放入字符串时才尝试转换为文本。
get 是保留的内置命令名。表达式插值和字面美元符的规则见字符串。
(let files (list "a file.rs" other.rs))(printf "<%s>\n" $files)(for file (glob *.rs) (echo $file))列表作为外部命令参数时会展开一层。文本始终保持为一个参数,即使其中包含空格或换行。
list 构造列表,str 拼接标量值;数值使用与命令参数、环境变量相同的格式转换为文本。
glob 显式匹配文件,返回排序后的路径列表,
没有匹配项时返回空列表。普通裸词、字符串和变量值都不会隐式进行通配符展开、分词或波浪号展开。
cd 接受一个路径,不提供路径时使用 $HOME,并更新 $PWD 和 $OLDPWD。
相对命令路径、glob 模式和重定向路径均以当前工作目录为基准。
map 接受交替的文本键和值,(map) 创建空映射。
键可以是裸词、字符串、文本变量或返回文本的表达式,其他类型会报错。
值保留原始类型,可以包含列表或嵌套映射。键和值从左到右各求值一次。
参数个数为奇数时,在求值前报错;重复键在第二次出现的位置报错,不再求值该键对应的值。
(let config (map name parsh version #1 nested (map enabled #true)))(let updated (map/set $config name new-name))(map/get $config name)(map/get $updated name)(map/get $config missing fallback)(map/keys $config)(set config (map/del $updated version))所有 m 命令的首参都是映射值,可以是 $config、映射字面量或返回映射的表达式。
裸词 config 表示文本,会报类型错误。上例中 updated 包含新名字,
config 保持原值,直到最后的 set 才更新。
| 命令 | 结果 |
|---|---|
(map/get $config key) |
返回原始类型的值;缺键时报错 |
(map/get $config key default) |
总会求值 default,缺键时返回它 |
(map/set $config key value) |
返回新增或覆盖该值后的新映射 |
(map/del $config key) |
返回删除该键后的新映射;缺键时报错 |
(map/has $config key) |
返回键是否存在的布尔值 |
(map/keys $config) |
按插入顺序返回文本键列表 |
(map/vals $config) |
按相同顺序返回值列表 |
(map/len $config) |
返回整数条目数 |
已存在且值为 nil 的键仍然存在,返回 nil;显式默认值仍会求值。
默认值不会处理变量未定义或首参类型错误。
操作先检查参数个数,再从左到右各求值一次。map/get 求值全部实参后检查映射并选择结果;
其余映射操作在首参通过映射类型检查后才继续求值键和值表达式。
操作使用这份独立的映射值;后续表达式即使修改来源变量,也不会改变已经取得的映射。
构造映射和 map/set 的键类型错误时,不再求值对应的值表达式。
映射操作可以直接组合,无需先绑定中间结果:
(map/set {name parsh} version v1)(map/get (map/set $config name other) name)(map/set (map/set $config name other) version v2)更新已有键保留原位置,新键追加到末尾。删除不改变其余键的相对顺序,重新插入追加到末尾。
映射按插入顺序显示为 (map "name" "parsh");eq 比较内容时忽略该顺序。
map/set 和 map/del 返回新映射,输入值保持原值。例如 (let copy $config) 之后,
(set config (map/set $config name changed)) 只更新 config,copy 及其嵌套数据保持原值。
函数可以用 set 更新捕获的外层绑定,同名形参则是独立绑定。
函数返回更新后的映射时,调用者显式赋回才会更新自己的变量。
map/get 和 map/vals 返回的值也各自独立。
映射不能隐式转为文本:str、字符串插值、外部命令参数和环境变量值都不接受映射。
需要列表用于循环或命令参数时,显式调用 map/keys 或 map/vals。
上一次执行结果
Section titled “上一次执行结果”只读特殊变量 $?(也可用 (get ?) 读取)保存上一次完整 CallResult,初始为 nil。使用 (exit-code $?)、(signal $?) 查询终止原因,或 (let saved $?) 保存快照。它不是环境变量,不能赋值。详见执行结果。