定义

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)。

→ 下一篇 闭包与作用域