Lua 函数使用的完备指南

[复制链接]
发表于 2025-9-30 00:47:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×


在 Lua 中,函数是一等公民(First-Class Citizen),这意味着函数可以像其他值一样被赋值、转达和操纵。以下是 Lua 函数界说的完备指南,涵盖底子语法、高级特性、操持模式及性能优化。




一、底子语法

1. 函数声明

  1. -- 基础语法
  2. function add(a, b)
  3.     return a + b
  4. end
  5. -- 调用
  6. print(add(3, 5))  -- 输出 8
复制代码
2. 匿名函数

  1. -- 无名称的函数(常用于回调)
  2. local function factorial(n)
  3.     return n == 0 and 1 or n * factorial(n-1)
  4. end
  5. -- 将函数赋值给变量
  6. local square = function(x) return x * x end
  7. print(square(4))  -- 输出 16
复制代码

二、焦点特性

1. 多返回值

  1. function divide_and_remainder(a, b)
  2.     return math.floor(a / b), a % b
  3. end
  4. local quotient, remainder = divide_and_remainder(10, 3)
  5. print(quotient, remainder)  -- 输出 3 1
复制代码
2. 变参函数(Variadic Function)

  1. -- 使用 ... 接收任意数量参数
  2. function sum(...)
  3.     local total = 0
  4.     for _, v in ipairs({...}) do
  5.         total = total + v
  6.     end
  7.     return total
  8. end
  9. print(sum(1,2,3,4))  -- 输出 10
复制代码
3. 函数作为返回值

  1. function make_adder(x)
  2.     return function(y)
  3.         return x + y
  4.     end
  5. end
  6. local add5 = make_adder(5)
  7. print(add5(3))  -- 输出 8
复制代码

三、进阶特性

1. 闭包(Closure)

闭包是函数与其词法环境的组合,可捕捉外部变量:
  1. function counter()
  2.     local count = 0
  3.     return function()
  4.         count = count + 1
  5.         return count
  6.     end
  7. end
  8. local c = counter()
  9. print(c())  -- 1
  10. print(c())  -- 2
复制代码
2. 尾调用优化(Tail Call Optimization)

尾调用不会增长调用栈深度,防止栈溢出:
  1. function factorial(n, acc)
  2.     acc = acc or 1
  3.     if n == 0 then return acc end
  4.     return factorial(n-1, n*acc)  -- 尾递归优化
  5. end
  6. print(factorial(5))  -- 输出 120
复制代码
3. 高阶函数(Higher-Order Function)

函数作为参数或返回值:
  1. -- map 函数
  2. function map(t, fn)
  3.     local result = {}
  4.     for _, v in ipairs(t) do
  5.         table.insert(result, fn(v))
  6.     end
  7.     return result
  8. end
  9. local numbers = {1,2,3,4}
  10. local squares = map(numbers, function(x) return x*x end)
  11. print(table.unpack(squares))  -- 输出 1 4 9 16
复制代码

四、函数属性与元编程

1. 函数属性

  1. function greet(name)
  2.     return "Hello, " .. name
  3. end
  4. greet.__call = function(self, ...)
  5.     return self.name .. ", " .. ...
  6. end
  7. setmetatable(greet, { __call = function(f, name) return "Hi, "..name end })
  8. print(greet("Alice"))  -- 输出 Hi, Alice
复制代码
2. 元表与函数钩子

  1. -- 统计函数调用次数
  2. local call_counts = {}
  3. local function hook(func)
  4.     return function(...)
  5.         call_counts[func] = (call_counts[func] or 0) + 1
  6.         return func(...)
  7.     end
  8. end
  9. local function add(a, b)
  10.     return a + b
  11. end
  12. add = hook(add)
  13. add(1,2)
  14. add(3,4)
  15. print(call_counts[add])  -- 输出 2
复制代码

五、性能优化指南

1. 克制闭包滥用

  1. -- 低效写法:频繁创建闭包
  2. for i = 1, 1000 do
  3.     local function fn() return i end  -- 每次循环都创建新闭包
  4. end
  5. -- 优化写法:使用局部变量捕获
  6. for i = 1, 1000 do
  7.     local i_local = i
  8.     local function fn() return i_local end
  9. end
复制代码
2. 内联小函数

  1. -- 频繁调用的简单函数可内联
  2. -- 优化前
  3. local function square(x) return x*x end
  4. for i = 1, 1e6 do
  5.     square(i)
  6. end
  7. -- 优化后
  8. for i = 1, 1e6 do
  9.     local x = i*i  -- 直接展开计算
  10. end
复制代码
3. 使用局部函数

  1. -- 全局函数查找较慢
  2. function global_fn() end
  3. -- 优化:优先使用局部函数
  4. local local_fn = function() end
复制代码

六、操持模式与最佳实践

1. 战略模式

  1. local strategies = {
  2.     add = function(a,b) return a+b end,
  3.     multiply = function(a,b) return a*b end
  4. }
  5. function calculate(operation, a, b)
  6.     return (strategies[operation] or strategies.add)(a, b)
  7. end
  8. print(calculate("multiply", 3,4))  -- 输出 12
复制代码
2. 工厂模式

  1. local function create_user(name, age)
  2.     return {
  3.         name = name,
  4.         age = age,
  5.         greet = function(self)
  6.             print("I'm", self.name)
  7.         end
  8.     }
  9. end
  10. local alice = create_user("Alice", 30)
  11. alice:greet()  -- 输出 I'm Alice
复制代码
3. 观察者模式

  1. local function observable()
  2.     local listeners = {}
  3.     return setmetatable({}, {
  4.         __newindex = function(t,k,v)
  5.             rawset(t, k, v)
  6.             for _, listener in ipairs(listeners) do
  7.                 listener(k, v)
  8.             end
  9.         end,
  10.         add_listener = function(t, listener)
  11.             table.insert(listeners, listener)
  12.         end
  13.     })
  14. end
  15. local obj = observable()
  16. obj:add_listener(function(key, value)
  17.     print("Property changed:", key, value)
  18. end)
  19. obj.x = 10  -- 触发监听器输出
复制代码

七、调试与元信息

1. 获取函数信息

  1. function example(a, b)
  2.     return a + b
  3. end
  4. print(debug.getinfo(example).name)  -- 输出 "example"
  5. print(debug.getupvalue(example, 1))  -- 查看闭包的上层变量(若有)
复制代码
2. 函数重载(模仿)

  1. local function overloaded(fn)
  2.     local cache = {}
  3.     return function(...)
  4.         local key = table.concat({...}, "|")
  5.         if not cache[key] then
  6.             cache[key] = fn(...)
  7.         end
  8.         return cache[key]
  9.     end
  10. end
  11. local function process(a, b)
  12.     return a + b
  13. end
  14. local process_overloaded = overloaded(process)
  15. print(process_overloaded(1,2))  -- 计算并缓存
  16. print(process_overloaded(1,2))  -- 直接返回缓存结果
复制代码

八、常见题目与办理方案

题目1:函数参数过多时的处理处罚

  1. -- 使用表传递可选参数
  2. function config(options)
  3.     local defaults = {width=800, height=600}
  4.     for k, v in pairs(options) do
  5.         defaults[k] = v
  6.     end
  7.     return defaults
  8. end
  9. local cfg = config({height=400})
  10. print(cfg.width, cfg.height)  -- 输出 800 400
复制代码
题目2:递归深度过大导致栈溢出

  1. -- 尾递归优化版本
  2. function fibonacci(n, a, b)
  3.     a = a or 0
  4.     b = b or 1
  5.     if n == 0 then return a end
  6.     if n == 1 then return b end
  7.     return fibonacci(n-1, b, a+b)
  8. end
  9. print(fibonacci(1000))  -- 不会导致栈溢出
复制代码

通过把握这些函数特性与模式,你可以编写出高效、机动的 Lua 代码。对于复杂场景,发起联合元编程和操持模式,同时注意性能优化细节。

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表