文章目录

Lua 函数:function 定义与闭包

发布于 2026-04-08 20:21:45 · 浏览 5 次 · 评论 0 条

Lua 函数:function 定义与闭包

Lua 中的函数是一等公民,这意味着它们可以像其他数据类型(如数字或字符串)一样被存储、传递和返回。掌握函数的定义与闭包机制,是编写高质量 Lua 代码的基础。以下是具体的操作指南。


1. 定义基础函数

编写 函数最常见的方式是使用 function 关键字,并以 end 结尾。

输入 以下代码定义一个简单的加法函数:

function add(a, b)
    return a + b
end

调用 该函数并打印结果:

local result = add(10, 20)
print(result) -- 输出 30

使用 局部函数定义来避免污染全局命名空间。在 function 前面加上 local

local function multiply(x, y)
    return x * y
end

注意 Lua 支持将函数赋值给变量,这种写法完全等同于上面的定义:

local divide = function(a, b)
    return a / b
end

2. 处理多返回值

与其他语言不同,Lua 函数天然支持返回多个结果。列出 所有需要返回的值,用逗号分隔。

编写 一个同时返回最大值和最小值的函数:

function getMinMax(a, b, c)
    local maxVal = math.max(a, b, c)
    local minVal = math.min(a, b, c)
    return maxVal, minVal
end

接收 返回值时,匹配 相同数量的变量:

local max, min = getMinMax(5, 2, 8)
print("Max:", max) -- 输出 Max: 8
print("Min:", min) -- 输出 Min: 2

注意 如果接收变量的数量少于返回值数量,多余的返回值会被丢弃;如果接收变量更多,多余的变量会被赋值为 nil


3. 理解与使用闭包

闭包是指一个函数加上它所需访问的外部“非局部变量”(upvalue)。利用 闭包可以创建数据的私有封装,类似面向对象中的成员变量。

创建 一个简单的计数器工厂函数:

function createCounter()
    local count = 0  -- 这是一个非局部变量(upvalue)

    -- 返回的匿名函数构成了闭包
    return function()
        count = count + 1
        return count
    end
end

实例化 两个独立的计数器:

local counter1 = createCounter()
local counter2 = createCounter()

print(counter1()) -- 输出 1
print(counter1()) -- 输出 2
print(counter2()) -- 输出 1 (counter2 拥有独立的 count 变量)

为了更直观地理解闭包的变量捕获机制,请参考下面的逻辑流程图:

graph LR A["Function createCounter"] --> B["Local Variable: count = 0"] B --> C["Return Anonymous Function"] C --> D["Closure Instance 1: count"] C --> E["Closure Instance 2: count"] D --> F["Modify own count"] E --> G["Modify own count"] F -.->|Independent| G

闭包使得 count 变量一直保存在内存中,不会被垃圾回收,直到闭包本身被销毁。


4. 接收变长参数

当不确定函数需要接收多少个参数时,使用 ... (三个点)来表示变长参数。

编写 一个求任意数量数字之和的函数:

local function sum(...)
    local total = 0
    -- **遍历** 变长参数表
    for i, v in ipairs({...}) do
        total = total + v
    end
    return total
end

调用 时传入任意数量的参数:

print(sum(1, 2, 3))        -- 输出 6
print(sum(10, 20, 30, 40)) -- 输出 100

如果需要将参数传递给另一个函数,使用 arg 表(Lua 5.1/5.2 常用方式)或者直接在 Lua 5.2+ 中使用 table.pack 处理。


5. 尾调用优化

尾调用是指一个函数的最后一步动作仅仅是调用另一个函数。确保 调用语句是 return func(args) 的形式,后面没有任何其他操作。

编写 一个非尾调用的例子(无法优化):

function f(x)
    return g(x) + 1  -- 调用 g 后还需要做加法,不是尾调用
end

修改 为尾调用优化版本:

function f(x)
    -- 将 g 的结果和后续操作传入新函数
    return g_add_one(x) 
end

-- 或者直接将逻辑调整,使得 f 的最后一步只调用 g
function f(x)
    return g(x) 
end

注意 尾调用优化不会消耗额外的栈空间,这意味着你可以进行无限递归而不会发生“栈溢出”错误。检查 你的代码,确保在深度递归场景下正确使用了尾调用。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文