函数和控制流
这一页集中说明 Lux 在 Lua 之上增加的日常语法。它们的目标不是把 Lua 变成另一种 完全不同的语言,而是把 GLua 里最常见的样板写法压缩掉,同时保留可预测的编译结果。
下面的“编译后 Lua”展示的是语义等价的生成形态。实际输出里的临时变量名可能不同,
但求值顺序、nil 判断和返回行为应保持一致。
fn 函数
fn 是 Lux 的函数声明语法。简单名字的顶层 fn 会创建模块私有绑定,不会写入
全局表,也不会自动导出。
块函数使用花括号。函数体最后一个没有分号的表达式会作为隐式返回值。
简单名字的 fn 会被绑定提升,所以同一作用域内可以前向调用,也可以互相递归。提升
的是函数绑定,不是普通语句的执行顺序。
默认参数
默认参数只在对应实参是 nil 或没有传入时触发。false、0、空字符串都不会触发
默认值。这一点不能用 Lua 的 or 直接模拟。
默认值按参数顺序处理,后面的默认值可以读取前面已经处理过的参数。反过来读取后面的 参数虽然按普通词法查找处理,但可读性很差,不建议这样写。
GLua 方法声明
Lux 保留 GLua 惯用的点号和冒号方法声明,方便给 ENT、SWEP、PANEL 这类已有表
挂方法。
这些声明是对已有表路径的赋值,不是模块私有绑定,也不会自动导出。普通模块 API 应
使用简单名字,再用 export 暴露。
隐式返回和分号
函数体、if 分支块和 do 表达式都使用同一套块值规则:最后一个没有分号的表达式
就是块的值。函数体走到这个尾表达式时,会返回它。
如果最后一行只是副作用,用分号压制隐式返回。GMod 的 Paint、Think、输入回调
通常都应这样写,除非你明确要返回值。
显式 return 始终优先,适合 Lua 多返回值、提前返回和回调转发。
条件表达式
if { ... } else { ... } 可以作为表达式使用。每个分支的值来自分支块的尾表达式。
短条件写成 cond then yes else no。它是语言级条件表达式,不是 Lua 的
and/or 技巧,所以 yes 为 false 时也不会被错误替换成 no。
Guard 语句
stopif 用于提前返回。它的基本形式是:
省略返回值时就是普通 return。stopifn 是反向形式,条件不成立时返回。
循环内可以使用 continueif 和 breakif。这两个语句只在循环体内合法。
箭头函数
=> 创建普通匿名函数,适合传给数组工具、hook 包装、一次性回调。
-> 创建带隐式 self 参数的匿名函数。它适合直接写 GLua 风格的面板回调。->
内部的 self 是新参数,会遮蔽外层同名变量。
可选访问
Lux 提供三种直接段可选访问:
obj?.field:安全读取字段obj?.fn(args):安全点号调用,不注入selfobj?:method(args):安全冒号调用,会注入selftbl?.[key]:安全索引
可选访问只保护被标记的那一段,不会自动保护后续普通访问或调用。
安全索引会先检查接收者,再求值索引表达式。因此 tbl?.[makeKey()] 在 tbl 为
nil 时不会调用 makeKey()。
不要把 factory?.Make()() 误认为整条链都安全。它只保护 factory?.Make(),
最后的 () 仍是普通调用。
?? nil 合并
?? 只在左侧结果为 nil 时使用右侧。它不会把 false 当成空值。
?? 和比较运算混用时要写括号,避免语义不清。
关系比较遇到可选链产生的 nil 会得到 false,不会对 nil 做大小比较。
解构绑定
对象解构读取字段,数组解构读取 Lua 的一基数组位置。默认值同样只在取到 nil 时
使用。
右侧表达式只求值一次。解构不会自动保护 nil,需要接受空值时先兜底:
表展开
表构造支持 ...table 展开。展开使用 pairs 拷贝键值,后面的字段覆盖前面的字段。
nil 展开源会被忽略。
表展开只复制可枚举键值,不复制 metatable。如果 metatable 有意义,需要手动处理。
复合赋值
Lux 支持 +=、-=、*=、/=、%=、^=、..=。复合赋值是语句,不是表达式。
复杂左值只求值一次,避免 getPlayer().score += 1 这种写法重复调用左侧表达式。
管道
管道 |> 使用显式占位符 %。左侧值只求值一次,并替换右侧当前步骤里的 %。
Lux 不会隐式把左侧塞进第一个参数;右侧必须出现 %。
% 的作用域很浅,不会进入嵌套函数。下面写法是错误的:
需要在嵌套函数中读取管道值时,先把管道值绑定到局部变量。
do 表达式
do { ... } 可以出现在表达式位置,用来把一段局部计算收拢成一个值。
没有尾表达式时,do 表达式的值是 nil。在语句位置,do { ... } 只是普通的
局部作用域。
模板字符串
反引号字符串支持 ${...} 插值。嵌入表达式会用 tostring 转成字符串,静态文本
原样保留。
如果要输出字面量 ${...},使用转义形式 \${...}。
多返回值和可变参数
Lux 保留 Lua 多返回值语义。普通函数调用在 Lua 敏感位置会保留多返回值,例如
return f()、局部多重绑定、调用参数列表的最后一项、表数组项的最后一项。
在普通表达式位置,调用结果仍像 Lua 一样折叠成单值。需要保留多个结果时,把它放在 Lua 本来就会展开的位置。