定义
function add(a, b)
return a + b
end
-- 等价于:
add = function(a, b) return a + b end
默认全局——必须用 local:
local function add(a, b)
return a + b
end
函数是一等公民
local function apply(fn, x) return fn(x) end
apply(print, "hi") -- hi
apply(function(x) return x*2 end, 5) -- 10
local handlers = { add = function(a,b) return a+b end }
print(handlers.add(1, 2)) -- 3
可以传参、返回、存表里——和 JS 完全一样。
多返回值
local function minmax(t)
return math.min(table.unpack(t)), math.max(table.unpack(t))
end
local lo, hi = minmax({3, 1, 4, 1, 5})
print(lo, hi) -- 1 5
调用方接几个就接几个:
local a = minmax({3, 1, 4}) -- a = 1(多余的丢)
local a, b, c = minmax({3, 1, 4}) -- a=1, b=4, c=nil
坑:多返回值在表达式中只展开为 1 个,除非在最后:
local t = {minmax({3,1,4}), "x"} -- t = {1, "x"} ← 只取第一个!
local t2 = {"x", minmax({3,1,4})} -- t2 = {"x", 1, 4} ← 末位才展开
用 (expr) 强制单返回值:
local a, b = (minmax({3,1,4})) -- a=1, b=nil
变长参数 ...
local function sum(...)
local args = {...}
local s = 0
for _, v in ipairs(args) do s = s + v end
return s
end
print(sum(1, 2, 3, 4)) -- 10
select:
local function debug_log(...)
print("got", select("#", ...), "args") -- 个数
print(select(2, ...)) -- 从第 2 个开始
end
debug_log("a", "b", "c")
-- got 3 args
-- b c
命名参数
Lua 没语法支持,但 table 顶替:
local function create_user(opts)
return {
name = opts.name or "anonymous",
age = opts.age or 0,
email = opts.email,
}
end
local u = create_user{ name = "Alice", age = 30 }
-- 注意:函数调用只有一个表参数时,可以省略括号
f{...} 是 f({...}) 的语法糖。f"..." 同理。
默认参数
无原生支持。or:
local function greet(name)
name = name or "world"
print("Hello " .. name)
end
注意:false 也会触发默认值。要区分用 if name == nil:
if x == nil then x = default end
闭包
每次定义都创建独立闭包:
local function counter()
local n = 0
return function()
n = n + 1
return n
end
end
local c1 = counter()
local c2 = counter()
print(c1()) -- 1
print(c1()) -- 2
print(c2()) -- 1 (独立 n)
详见 第 08 篇。
函数定义糖
function M.add(a, b) ... end -- 等价 M.add = function(a, b) ... end
function obj:method(x) ... end -- 等价 obj.method = function(self, x) ... end
: 自动添加 self 第一个参数——OOP 的基础(第 10 篇)。
尾调用
Lua 保证尾调用消除(tail call elimination):
local function loop(n)
if n == 0 then return "done" end
return loop(n - 1) -- 真·尾调用,不占栈
end
loop(10000000) -- 不爆栈
注意:return f(x) + 1 不是尾调用(return 前还要加 1)。
→ 下一篇 闭包与作用域