在 Lua 中,函数是一等公民(First-Class Citizen),这意味着函数可以像其他值一样被赋值、传递和操作。以下是 Lua 函数定义的完整指南,涵盖基础语法、高级特性、设计模式及性能优化。
在Lua 中,函数定义的完整指南---目录
- 一、基础语法
-
- [1. 函数声明](#1. 函数声明)
- [2. 匿名函数](#2. 匿名函数)
- 二、核心特性
-
- [1. 多返回值](#1. 多返回值)
- [2. 变参函数(Variadic Function)](#2. 变参函数(Variadic Function))
- [3. 函数作为返回值](#3. 函数作为返回值)
- 三、进阶特性
-
- [1. 闭包(Closure)](#1. 闭包(Closure))
- [2. 尾调用优化(Tail Call Optimization)](#2. 尾调用优化(Tail Call Optimization))
- [3. 高阶函数(Higher-Order Function)](#3. 高阶函数(Higher-Order Function))
- 四、函数属性与元编程
-
- [1. 函数属性](#1. 函数属性)
- [2. 元表与函数钩子](#2. 元表与函数钩子)
- 五、性能优化指南
-
- [1. 避免闭包滥用](#1. 避免闭包滥用)
- [2. 内联小函数](#2. 内联小函数)
- [3. 使用局部函数](#3. 使用局部函数)
- 六、设计模式与最佳实践
-
- [1. 策略模式](#1. 策略模式)
- [2. 工厂模式](#2. 工厂模式)
- [3. 观察者模式](#3. 观察者模式)
- 七、调试与元信息
-
- [1. 获取函数信息](#1. 获取函数信息)
- [2. 函数重载(模拟)](#2. 函数重载(模拟))
- 八、常见问题与解决方案
一、基础语法
1. 函数声明
lua
-- 基础语法
function add(a, b)
return a + b
end
-- 调用
print(add(3, 5)) -- 输出 8
2. 匿名函数
lua
-- 无名称的函数(常用于回调)
local function factorial(n)
return n == 0 and 1 or n * factorial(n-1)
end
-- 将函数赋值给变量
local square = function(x) return x * x end
print(square(4)) -- 输出 16
二、核心特性
1. 多返回值
lua
function divide_and_remainder(a, b)
return math.floor(a / b), a % b
end
local quotient, remainder = divide_and_remainder(10, 3)
print(quotient, remainder) -- 输出 3 1
2. 变参函数(Variadic Function)
lua
-- 使用 ... 接收任意数量参数
function sum(...)
local total = 0
for _, v in ipairs({...}) do
total = total + v
end
return total
end
print(sum(1,2,3,4)) -- 输出 10
3. 函数作为返回值
lua
function make_adder(x)
return function(y)
return x + y
end
end
local add5 = make_adder(5)
print(add5(3)) -- 输出 8
三、进阶特性
1. 闭包(Closure)
闭包是函数与其词法环境的组合,可捕获外部变量:
lua
function counter()
local count = 0
return function()
count = count + 1
return count
end
end
local c = counter()
print(c()) -- 1
print(c()) -- 2
2. 尾调用优化(Tail Call Optimization)
尾调用不会增加调用栈深度,防止栈溢出:
lua
function factorial(n, acc)
acc = acc or 1
if n == 0 then return acc end
return factorial(n-1, n*acc) -- 尾递归优化
end
print(factorial(5)) -- 输出 120
3. 高阶函数(Higher-Order Function)
函数作为参数或返回值:
lua
-- map 函数
function map(t, fn)
local result = {}
for _, v in ipairs(t) do
table.insert(result, fn(v))
end
return result
end
local numbers = {1,2,3,4}
local squares = map(numbers, function(x) return x*x end)
print(table.unpack(squares)) -- 输出 1 4 9 16
四、函数属性与元编程
1. 函数属性
lua
function greet(name)
return "Hello, " .. name
end
greet.__call = function(self, ...)
return self.name .. ", " .. ...
end
setmetatable(greet, { __call = function(f, name) return "Hi, "..name end })
print(greet("Alice")) -- 输出 Hi, Alice
2. 元表与函数钩子
lua
-- 统计函数调用次数
local call_counts = {}
local function hook(func)
return function(...)
call_counts[func] = (call_counts[func] or 0) + 1
return func(...)
end
end
local function add(a, b)
return a + b
end
add = hook(add)
add(1,2)
add(3,4)
print(call_counts[add]) -- 输出 2
五、性能优化指南
1. 避免闭包滥用
lua
-- 低效写法:频繁创建闭包
for i = 1, 1000 do
local function fn() return i end -- 每次循环都创建新闭包
end
-- 优化写法:使用局部变量捕获
for i = 1, 1000 do
local i_local = i
local function fn() return i_local end
end
2. 内联小函数
lua
-- 频繁调用的简单函数可内联
-- 优化前
local function square(x) return x*x end
for i = 1, 1e6 do
square(i)
end
-- 优化后
for i = 1, 1e6 do
local x = i*i -- 直接展开计算
end
3. 使用局部函数
lua
-- 全局函数查找较慢
function global_fn() end
-- 优化:优先使用局部函数
local local_fn = function() end
六、设计模式与最佳实践
1. 策略模式
lua
local strategies = {
add = function(a,b) return a+b end,
multiply = function(a,b) return a*b end
}
function calculate(operation, a, b)
return (strategies[operation] or strategies.add)(a, b)
end
print(calculate("multiply", 3,4)) -- 输出 12
2. 工厂模式
lua
local function create_user(name, age)
return {
name = name,
age = age,
greet = function(self)
print("I'm", self.name)
end
}
end
local alice = create_user("Alice", 30)
alice:greet() -- 输出 I'm Alice
3. 观察者模式
lua
local function observable()
local listeners = {}
return setmetatable({}, {
__newindex = function(t,k,v)
rawset(t, k, v)
for _, listener in ipairs(listeners) do
listener(k, v)
end
end,
add_listener = function(t, listener)
table.insert(listeners, listener)
end
})
end
local obj = observable()
obj:add_listener(function(key, value)
print("Property changed:", key, value)
end)
obj.x = 10 -- 触发监听器输出
七、调试与元信息
1. 获取函数信息
lua
function example(a, b)
return a + b
end
print(debug.getinfo(example).name) -- 输出 "example"
print(debug.getupvalue(example, 1)) -- 查看闭包的上层变量(若有)
2. 函数重载(模拟)
lua
local function overloaded(fn)
local cache = {}
return function(...)
local key = table.concat({...}, "|")
if not cache[key] then
cache[key] = fn(...)
end
return cache[key]
end
end
local function process(a, b)
return a + b
end
local process_overloaded = overloaded(process)
print(process_overloaded(1,2)) -- 计算并缓存
print(process_overloaded(1,2)) -- 直接返回缓存结果
八、常见问题与解决方案
问题1:函数参数过多时的处理
lua
-- 使用表传递可选参数
function config(options)
local defaults = {width=800, height=600}
for k, v in pairs(options) do
defaults[k] = v
end
return defaults
end
local cfg = config({height=400})
print(cfg.width, cfg.height) -- 输出 800 400
问题2:递归深度过大导致栈溢出
lua
-- 尾递归优化版本
function fibonacci(n, a, b)
a = a or 0
b = b or 1
if n == 0 then return a end
if n == 1 then return b end
return fibonacci(n-1, b, a+b)
end
print(fibonacci(1000)) -- 不会导致栈溢出
通过掌握这些函数特性与模式,你可以编写出高效、灵活的 Lua 代码。对于复杂场景,建议结合元编程和设计模式,同时注意性能优化细节。