第 6 章 函数
第 6 章 函数
函数是 Lua 的一等值,可以赋值给变量、传给其他函数,也可以作为返回值。函数与闭包是 Lua 设计中最有表达力的部分之一。
定义与调用函数
local function add(a, b)
return a + b
end
print(add(2, 3))
函数也可以使用匿名函数表达式:
local multiply = function(a, b)
return a * b
end
print(multiply(4, 5))
调用函数时参数不足会补 nil,参数过多会被忽略:
local function show(a, b)
print(a, b)
end
show(1)
show(1, 2, 3)
多返回值
Lua 函数可以返回多个值:
local function minMax(values)
local minValue = math.huge
local maxValue = -math.huge
for _, value in ipairs(values) do
minValue = math.min(minValue, value)
maxValue = math.max(maxValue, value)
end
return minValue, maxValue
end
local minimum, maximum = minMax({ 4, 2, 9, 1 })
print(minimum, maximum)
多返回值只在调用表达式处于允许的位置时全部保留。放入表时需要额外处理:
local function values()
return 1, 2, 3
end
local first = { values() }
local second = { values(), 4 }
print(#first) -- 3
print(#second) -- 2
可变参数
使用 ... 接收任意数量参数:
local function sum(...)
local total = 0
for _, value in ipairs({ ... }) do
total = total + value
end
return total
end
也可以使用 select:
local function inspect(...)
print("数量:", select("#", ...))
for index = 1, select("#", ...) do
print(index, select(index, ...))
end
end
inspect("a", "b", "c")
转发参数
local function log(level, ...)
io.write("[" .. level .. "] ")
print(...)
end
log("INFO", "server", "started")
作用域与闭包
函数可以捕获外部局部变量,即使定义它的函数已经返回:
local function makeCounter()
local count = 0
return function()
count = count + 1
return count
end
end
local nextNumber = makeCounter()
print(nextNumber()) -- 1
print(nextNumber()) -- 2
每个闭包实例拥有独立的环境。多个闭包可以共享同一组变量:
local function makeAccount(initial)
local balance = initial
return {
deposit = function(amount)
balance = balance + amount
return balance
end,
withdraw = function(amount)
if amount > balance then
return nil, "余额不足"
end
balance = balance - amount
return balance
end
}
end
这种模式可以在不使用元表的情况下实现简单封装。
函数式编程基础
高阶函数
local function map(values, transform)
local result = {}
for index, value in ipairs(values) do
result[index] = transform(value)
end
return result
end
local doubled = map({ 1, 2, 3 }, function(value)
return value * 2
end)
过滤与归约
local function filter(values, predicate)
local result = {}
for _, value in ipairs(values) do
if predicate(value) then
result[#result + 1] = value
end
end
return result
end
local function reduce(values, initial, combine)
local accumulator = initial
for _, value in ipairs(values) do
accumulator = combine(accumulator, value)
end
return accumulator
end
函数式写法能减少临时状态,但不要把简单循环强行改写成多层高阶函数。选择团队最容易理解的表达方式。