马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
在 Lua 中,函数是一等公民(First-Class Citizen),这意味着函数可以像其他值一样被赋值、转达和操纵。以下是 Lua 函数界说的完备指南,涵盖底子语法、高级特性、操持模式及性能优化。
一、底子语法
1. 函数声明
- -- 基础语法
- function add(a, b)
- return a + b
- end
- -- 调用
- print(add(3, 5)) -- 输出 8
复制代码 2. 匿名函数
- -- 无名称的函数(常用于回调)
- 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. 多返回值
- 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)
- -- 使用 ... 接收任意数量参数
- 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. 函数作为返回值
- function make_adder(x)
- return function(y)
- return x + y
- end
- end
- local add5 = make_adder(5)
- print(add5(3)) -- 输出 8
复制代码 三、进阶特性
1. 闭包(Closure)
闭包是函数与其词法环境的组合,可捕捉外部变量:
- 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)
尾调用不会增长调用栈深度,防止栈溢出:
- 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)
函数作为参数或返回值:
- -- 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. 函数属性
- 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. 元表与函数钩子
- -- 统计函数调用次数
- 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. 克制闭包滥用
- -- 低效写法:频繁创建闭包
- 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. 内联小函数
- -- 频繁调用的简单函数可内联
- -- 优化前
- 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. 使用局部函数
- -- 全局函数查找较慢
- function global_fn() end
- -- 优化:优先使用局部函数
- local local_fn = function() end
复制代码 六、操持模式与最佳实践
1. 战略模式
- 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. 工厂模式
- 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. 观察者模式
- 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. 获取函数信息
- function example(a, b)
- return a + b
- end
- print(debug.getinfo(example).name) -- 输出 "example"
- print(debug.getupvalue(example, 1)) -- 查看闭包的上层变量(若有)
复制代码 2. 函数重载(模仿)
- 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:函数参数过多时的处理处罚
- -- 使用表传递可选参数
- 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:递归深度过大导致栈溢出
- -- 尾递归优化版本
- 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 代码。对于复杂场景,发起联合元编程和操持模式,同时注意性能优化细节。
|