Lua 小白入门教程Lua 小白入门教程
首页
基础教程
实战进阶
编程指南
首页
基础教程
实战进阶
编程指南
  • 基础教程

    • 📚 基础教程
    • 第1章 - Lua 是什么?
    • 第2章 - 环境搭建
    • 第3章 - 变量与数据类型
    • 第4章 - 运算符与表达式
    • 第5章 - 流程控制
    • 第6章 - 函数
    • 第7章 - Table(表)
    • 第8章 - 字符串与模式匹配

第6章 - 函数

嗨,朋友!我是长安。

函数是 Lua 中最强大的特性之一。Lua 的函数是一等公民(first-class),可以赋值给变量、作为参数传递、作为返回值——这些在 Java 8 之前是做不到的。

🚀 基本函数定义

Lua 写法

-- 定义一个函数
local function greet(name)
    print("你好," .. name .. "!")
end

-- 调用函数
greet("长安")    -- 你好,长安!

Java 写法

public void greet(String name) {
    System.out.println("你好," + name + "!");
}

greet("长安");   // 你好,长安!

语法对比

特性JavaLua
关键字无(用返回类型)function
参数类型必须声明不需要
返回类型必须声明不需要
结束标记}end
访问修饰符public/private 等无(用 local 控制作用域)

📤 返回值

单返回值

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

local result = add(3, 5)
print(result)    -- 8

🌟 多返回值(Java 做不到!)

-- Lua 函数可以返回多个值!
local function getPersonInfo()
    return "长安", 25, "Java开发"
end

local name, age, job = getPersonInfo()
print(name)     -- 长安
print(age)      -- 25
print(job)      -- Java开发

-- 只取部分返回值
local name2 = getPersonInfo()    -- 只取第一个
print(name2)    -- 长安

-- 用 _ 忽略不需要的值
local _, age2 = getPersonInfo()  -- 忽略第一个,取第二个
print(age2)     -- 25
// Java 不能直接返回多个值,通常用对象或数组
public class PersonInfo {
    String name;
    int age;
    String job;
}

// 或者用 Map
public Map<String, Object> getPersonInfo() {
    Map<String, Object> map = new HashMap<>();
    map.put("name", "长安");
    map.put("age", 25);
    map.put("job", "Java开发");
    return map;
}

多返回值

多返回值是 Lua 的一大特色!Java 需要用对象、数组、或 Pair/Tuple 来实现,而 Lua 直接支持。

📋 可变参数

-- 可变参数用 ...
local function sum(...)
    local args = {...}    -- 把可变参数收集到表中
    local total = 0
    for _, v in ipairs(args) do
        total = total + v
    end
    return total
end

print(sum(1, 2, 3))         -- 6
print(sum(1, 2, 3, 4, 5))   -- 15
// Java 的可变参数
public int sum(int... nums) {
    int total = 0;
    for (int n : nums) {
        total += n;
    }
    return total;
}

🎭 函数是一等公民

在 Lua 中,函数就是一个值,可以像普通变量一样使用:

-- 函数赋值给变量
local myPrint = print
myPrint("Hello!")    -- Hello!

-- 匿名函数(类似 Java 的 Lambda)
local add = function(a, b)
    return a + b
end
print(add(3, 5))     -- 8

-- 函数作为参数传递
local function applyOperation(a, b, operation)
    return operation(a, b)
end

print(applyOperation(10, 3, function(a, b) return a + b end))  -- 13
print(applyOperation(10, 3, function(a, b) return a * b end))  -- 30
// Java 8+ Lambda 等价写法
BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
System.out.println(add.apply(3, 5));  // 8

public int applyOperation(int a, int b, BiFunction<Integer, Integer, Integer> op) {
    return op.apply(a, b);
}
applyOperation(10, 3, (a, b) -> a + b);  // 13

🔒 闭包(Closure)

闭包是函数 + 它引用的外部变量:

local function createCounter()
    local count = 0          -- 外部变量(被闭包捕获)
    return function()        -- 返回一个闭包
        count = count + 1
        return count
    end
end

local counter = createCounter()
print(counter())    -- 1
print(counter())    -- 2
print(counter())    -- 3

-- 每个闭包有自己的独立环境
local counter2 = createCounter()
print(counter2())   -- 1(独立计数)
// Java 也有闭包(通过 Lambda 实现)
public Supplier<Integer> createCounter() {
    final int[] count = {0};   // Java Lambda 要求"事实上的 final"
    return () -> ++count[0];
}

Supplier<Integer> counter = createCounter();
System.out.println(counter.get());  // 1
System.out.println(counter.get());  // 2

闭包的实用场景

闭包在 Lua 中非常常用,常见的应用:

  1. 封装私有状态 — 类似 Java 的私有属性
  2. 回调函数 — 保存上下文信息
  3. 迭代器 — 自定义迭代行为
  4. 缓存/记忆化 — 缓存函数计算结果

📦 函数的两种定义方式

-- 方式一:标准写法
local function foo(x)
    return x * 2
end

-- 方式二:变量赋值写法(完全等价)
local foo = function(x)
    return x * 2
end

-- 方式一其实是方式二的语法糖

注意递归

如果函数需要递归调用自己,推荐用方式一:

-- ✅ 正确:标准写法支持递归
local function factorial(n)
    if n <= 1 then return 1 end
    return n * factorial(n - 1)
end

-- ❌ 可能出错:变量赋值写法
local factorial = function(n)
    if n <= 1 then return 1 end
    return n * factorial(n - 1)  -- 这里的 factorial 可能还是 nil!
end

🔧 常用的内置函数

-- 类型相关
print(type(42))         -- "number"
print(tostring(42))     -- "42"
print(tonumber("42"))   -- 42

-- 数学相关
print(math.max(1, 5, 3))    -- 5
print(math.min(1, 5, 3))    -- 1
print(math.floor(3.7))      -- 3
print(math.ceil(3.2))       -- 4
print(math.random(1, 100))  -- 随机数

-- 表(数组)相关
local t = {3, 1, 4, 1, 5}
table.sort(t)
table.insert(t, 9)          -- 在末尾插入
table.remove(t, 1)          -- 删除第一个元素

📝 小结

  • Lua 函数用 function ... end 定义,不需要声明参数类型和返回类型
  • 函数可以返回多个值,这是 Java 做不到的
  • 函数是一等公民,可以赋值、传参、返回
  • 闭包是 Lua 的强大特性,可以封装私有状态
  • 推荐使用 local function 定义函数

➡️ 下一步

函数掌握了!下一章我们来学习 Lua 最核心的数据结构——Table(表),它能当数组、字典、甚至对象用!

💪 练习题

  1. 写一个函数,接收两个数字,返回它们的和与差(两个返回值)。
  2. 写一个闭包,实现一个计数器,每次调用返回递增的值。
  3. 写一个函数,接收一个函数作为参数,对数组中的每个元素执行该函数。
  4. local function foo() 和 local foo = function() 有什么区别?

答案提示

  1. local function calc(a, b) return a + b, a - b end
  2. 参考本章的 createCounter 示例
  3. local function map(t, fn) for i, v in ipairs(t) do t[i] = fn(v) end end
  4. 前者支持递归调用自身,后者在递归时可能引用到 nil
最近更新: 2026/2/27 17:54
Contributors: 王长安
Prev
第5章 - 流程控制
Next
第7章 - Table(表)