函数基础 #

一、函数定义 #

1.1 基本语法 #

lua
-- 基本语法
function name(parameters)
    -- 函数体
    return value
end

-- 示例
function greet()
    print("Hello, Lua!")
end

greet()  -- Hello, Lua!

1.2 函数定义方式 #

lua
-- 方式1:全局函数
function greet1()
    print("Hello!")
end

-- 方式2:局部函数(推荐)
local function greet2()
    print("Hello!")
end

-- 方式3:函数表达式
local greet3 = function()
    print("Hello!")
end

-- 方式4:表方法
local obj = {}
function obj.method()
    print("方法")
end

-- 方式5:冒号语法(自动传递 self)
function obj:method2()
    print(self)  -- self 是 obj
end

1.3 函数命名规范 #

lua
-- 推荐:小写字母,下划线分隔
local function calculate_sum(a, b)
    return a + b
end

-- 返回布尔值的函数:is/has/can 前缀
local function is_valid(value)
    return value ~= nil
end

local function has_permission(user, action)
    return user.permissions[action] ~= nil
end

-- 获取值的函数:get 前缀
local function get_user_name(user)
    return user.name or "Unknown"
end

-- 设置值的函数:set 前缀
local function set_user_name(user, name)
    user.name = name
end

二、参数 #

2.1 基本参数 #

lua
-- 位置参数
local function add(a, b)
    return a + b
end

print(add(1, 2))  -- 3

-- 参数不足时补 nil
local function greet(name, greeting)
    greeting = greeting or "Hello"
    print(greeting .. ", " .. name .. "!")
end

greet("Lua")           -- Hello, Lua!
greet("Lua", "Hi")     -- Hi, Lua!

2.2 默认参数 #

lua
-- 使用 or 设置默认值
local function create_config(options)
    options = options or {}
    local config = {
        host = options.host or "localhost",
        port = options.port or 8080,
        timeout = options.timeout or 30
    }
    return config
end

local cfg = create_config()
print(cfg.host, cfg.port)  -- localhost    8080

local cfg2 = create_config({host = "example.com", port = 3000})
print(cfg2.host, cfg2.port)  -- example.com    3000

2.3 命名参数 #

lua
-- Lua 没有命名参数,但可以用表模拟
local function create_window(options)
    local width = options.width or 800
    local height = options.height or 600
    local title = options.title or "Window"
    
    print(string.format("窗口:%s (%dx%d)", title, width, height))
end

create_window {
    title = "My App",
    width = 1024,
    height = 768
}
-- 窗口:My App (1024x768)

2.4 参数验证 #

lua
-- 类型检查
local function process(data)
    if type(data) ~= "table" then
        error("参数必须是表", 2)
    end
    
    if not data.name then
        error("缺少 name 字段", 2)
    end
    
    return data.name
end

-- 使用 assert
local function divide(a, b)
    assert(type(a) == "number", "a 必须是数字")
    assert(type(b) == "number", "b 必须是数字")
    assert(b ~= 0, "除数不能为 0")
    return a / b
end

三、返回值 #

3.1 单返回值 #

lua
local function square(x)
    return x * x
end

local result = square(5)
print(result)  -- 25

3.2 多返回值 #

lua
-- 返回多个值
local function min_max(arr)
    local min, max = arr[1], arr[1]
    for _, v in ipairs(arr) do
        if v < min then min = v end
        if v > max then max = v end
    end
    return min, max
end

local minimum, maximum = min_max({3, 1, 4, 1, 5, 9})
print(minimum, maximum)  -- 1    9

-- 忽略部分返回值
local min, _ = min_max({1, 2, 3})
print(min)  -- 1

3.3 返回值的使用 #

lua
-- 作为函数参数
local function get_coords()
    return 10, 20
end

local function distance(x, y)
    return math.sqrt(x * x + y * y)
end

print(distance(get_coords()))  -- 22.36...

-- 在表中使用
local point = {get_coords()}
print(point[1], point[2])  -- 10    20

-- 多重赋值
local x, y, z = get_coords(), 30
print(x, y, z)  -- 10    20    30

-- 注意:只有最后一个表达式会展开多个返回值
local a, b, c = get_coords()
print(a, b, c)  -- 10    20    nil

3.4 返回表 #

lua
-- 返回多个命名值
local function get_user_info(id)
    return {
        id = id,
        name = "User" .. id,
        email = "user" .. id .. "@example.com",
        active = true
    }
end

local user = get_user_info(1)
print(user.name, user.email)

四、函数调用 #

4.1 基本调用 #

lua
-- 普通调用
function add(a, b)
    return a + b
end
print(add(1, 2))  -- 3

-- 单参数时可以省略括号
print "Hello"           -- Hello
print [[Hello World]]   -- Hello World

-- 表参数可以省略括号
local function process(options)
    print(options.name)
end
process {name = "Lua"}  -- Lua

4.2 方法调用 #

lua
local obj = {
    name = "Object",
    value = 42
}

-- 点语法
function obj.get_name(self)
    return self.name
end
print(obj.get_name(obj))  -- Object

-- 冒号语法(自动传递 self)
function obj:get_value()
    return self.value
end
print(obj:get_value())  -- 42

-- 冒号定义和调用
obj:method = function(self)
    print(self.name)
end
obj:method()  -- Object

4.3 链式调用 #

lua
local Calculator = {}
Calculator.__index = Calculator

function Calculator:new()
    return setmetatable({value = 0}, self)
end

function Calculator:add(n)
    self.value = self.value + n
    return self
end

function Calculator:sub(n)
    self.value = self.value - n
    return self
end

function Calculator:result()
    return self.value
end

-- 链式调用
local calc = Calculator:new()
local result = calc:add(10):sub(3):add(5):result()
print(result)  -- 12

五、递归函数 #

5.1 基本递归 #

lua
-- 阶乘
local function factorial(n)
    if n <= 1 then
        return 1
    end
    return n * factorial(n - 1)
end
print(factorial(5))  -- 120

-- 斐波那契
local function fib(n)
    if n <= 1 then
        return n
    end
    return fib(n - 1) + fib(n - 2)
end
print(fib(10))  -- 55

5.2 尾递归 #

lua
-- 普通递归(可能栈溢出)
local function sum(n)
    if n <= 0 then
        return 0
    end
    return n + sum(n - 1)  -- 不是尾递归
end

-- 尾递归优化
local function sum_tail(n, acc)
    acc = acc or 0
    if n <= 0 then
        return acc
    end
    return sum_tail(n - 1, acc + n)  -- 尾递归
end
print(sum_tail(10000))  -- 不会栈溢出

5.3 递归应用 #

lua
-- 遍历嵌套表
local function deep_print(t, indent)
    indent = indent or ""
    for k, v in pairs(t) do
        if type(v) == "table" then
            print(indent .. k .. ":")
            deep_print(v, indent .. "  ")
        else
            print(indent .. k .. ": " .. tostring(v))
        end
    end
end

-- 深拷贝
local function deep_copy(t)
    if type(t) ~= "table" then
        return t
    end
    
    local copy = {}
    for k, v in pairs(t) do
        copy[deep_copy(k)] = deep_copy(v)
    end
    return copy
end

六、匿名函数 #

6.1 基本用法 #

lua
-- 匿名函数
local greet = function(name)
    print("Hello, " .. name)
end
greet("Lua")

-- 作为参数
local arr = {3, 1, 4, 1, 5}
table.sort(arr, function(a, b)
    return a > b
end)
print(table.concat(arr, ", "))  -- 5, 4, 3, 1, 1

-- 立即执行函数
local result = (function(x)
    return x * x
end)(5)
print(result)  -- 25

6.2 高阶函数 #

lua
-- map 函数
local function map(arr, func)
    local result = {}
    for i, v in ipairs(arr) do
        result[i] = func(v, i)
    end
    return result
end

local doubled = map({1, 2, 3, 4, 5}, function(x)
    return x * 2
end)
print(table.concat(doubled, ", "))  -- 2, 4, 6, 8, 10

-- filter 函数
local function filter(arr, func)
    local result = {}
    for _, v in ipairs(arr) do
        if func(v) then
            table.insert(result, v)
        end
    end
    return result
end

local evens = filter({1, 2, 3, 4, 5}, function(x)
    return x % 2 == 0
end)
print(table.concat(evens, ", "))  -- 2, 4

-- reduce 函数
local function reduce(arr, func, initial)
    local acc = initial
    for _, v in ipairs(arr) do
        acc = func(acc, v)
    end
    return acc
end

local sum = reduce({1, 2, 3, 4, 5}, function(acc, v)
    return (acc or 0) + v
end, 0)
print(sum)  -- 15

七、函数作为值 #

7.1 函数赋值 #

lua
-- 函数可以赋值给变量
local f = print
f("Hello")  -- Hello

-- 函数可以存储在表中
local operations = {
    add = function(a, b) return a + b end,
    sub = function(a, b) return a - b end,
    mul = function(a, b) return a * b end,
    div = function(a, b) return a / b end
}

print(operations.add(10, 5))   -- 15
print(operations.mul(10, 5))   -- 50

7.2 函数作为参数 #

lua
-- 回调函数
local function process_async(data, callback)
    -- 模拟异步处理
    local result = data * 2
    callback(result)
end

process_async(10, function(result)
    print("结果:" .. result)
end)

-- 策略模式
local function calculate(a, b, strategy)
    return strategy(a, b)
end

print(calculate(10, 5, operations.add))  -- 15
print(calculate(10, 5, operations.mul))  -- 50

7.3 函数作为返回值 #

lua
-- 工厂函数
local function create_multiplier(factor)
    return function(x)
        return x * factor
    end
end

local double = create_multiplier(2)
local triple = create_multiplier(3)

print(double(5))  -- 10
print(triple(5))  -- 15

-- 条件返回函数
local function get_handler(type)
    if type == "json" then
        return function(data)
            return '{"data":"' .. data .. '"}'
        end
    elseif type == "xml" then
        return function(data)
            return "<data>" .. data .. "</data>"
        end
    else
        return function(data)
            return data
        end
    end
end

local handler = get_handler("json")
print(handler("hello"))  -- {"data":"hello"}

八、实用示例 #

8.1 防抖函数 #

lua
local function debounce(func, delay)
    local timer = nil
    return function(...)
        local args = {...}
        if timer then
            timer = nil  -- 取消之前的计时器
        end
        timer = setTimeout(function()  -- 假设有 setTimeout
            func(table.unpack(args))
        end, delay)
    end
end

8.2 记忆化 #

lua
local function memoize(func)
    local cache = {}
    return function(...)
        local key = table.concat({...}, ",")
        if cache[key] == nil then
            cache[key] = func(...)
        end
        return cache[key]
    end
end

local memo_fib = memoize(function(n)
    if n <= 1 then return n end
    return memo_fib(n - 1) + memo_fib(n - 2)
end)

print(memo_fib(40))  -- 快速计算

8.3 函数组合 #

lua
local function compose(...)
    local funcs = {...}
    return function(x)
        local result = x
        for i = #funcs, 1, -1 do
            result = funcs[i](result)
        end
        return result
    end
end

local double = function(x) return x * 2 end
local add_one = function(x) return x + 1 end
local square = function(x) return x * x end

local composed = compose(square, add_one, double)
print(composed(3))  -- ((3 * 2) + 1) ^ 2 = 49

九、总结 #

本章介绍了 Lua 函数的基础知识:

  1. 函数定义:多种定义方式
  2. 参数:位置参数、默认参数、命名参数
  3. 返回值:单返回值、多返回值
  4. 函数调用:普通调用、方法调用、链式调用
  5. 递归:基本递归、尾递归优化
  6. 匿名函数:作为参数和返回值
  7. 高阶函数:map、filter、reduce

函数是 Lua 编程的核心概念。下一章,我们将深入学习闭包和高阶函数。

最后更新:2026-03-27