# Lua 脚本入门

# 1. Lua 简介

Lua 是一种轻量级的、可嵌入的脚本语言。它由巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)的 Roberto Ierusalimschy、Luiz Henrique de Figueiredo 和 Waldemar Celes 等人开发。Lua 的设计目标是作为嵌入式脚本语言,它具有以下特点:

  • 轻量级:Lua 的核心语言非常简单,只有大约 30 个关键字,易于学习和使用。

  • 可嵌入:Lua 可以嵌入到其他应用程序中,作为脚本语言使用。它可以通过 C 语言的 API 与宿主应用程序进行交互。

  • 动态类型:Lua 是一种动态类型语言,变量无需声明类型,可以直接赋值。

  • 语法简洁:Lua 的语法非常简洁,易于阅读和编写。

  • 支持面向对象编程:Lua 支持面向对象编程,可以通过表(table)来实现类和对象。

  • 跨平台:Lua 可以在多种操作系统和硬件平台上运行,包括 Windows、Linux、Mac OS X、Android、iOS 等。

# 2. 基本语法

Lua5.3 参考手册

# 2.1 注释

Lua 支持单行注释和多行注释。

单行注释以两个连字符(--)开头,例如:

-- 这是一个单行注释

多行注释以两个连字符和两个连字符加一个连字符(--[[--]])开头和结尾,例如:

--[[
这是一个多行注释
可以跨越多行
--]]

Lua 不支持嵌套注释

# 2.2 标识符

Lua 标识符用于命名变量、函数等,规则如下:

  • 以字母(A-Z 或 a-z)或下划线(_)开头
  • 后跟零个或多个字母、数字(0-9)或下划线
  • 区分大小写
  • 不能使用特殊字符如 @、$、% 等
  • 避免使用下划线加大写字母的组合(如_VERSION),因为这类标识符通常被 Lua 内部使用

有效标识符示例:

name        -- 有效
_temp       -- 有效
var123      -- 有效
myVariable  -- 有效

无效标识符示例:

123var      -- 无效:不能以数字开头
my-var      -- 无效:不能包含连字符
my$var      -- 无效:不能包含特殊字符

# 2.3 关键字

Lua 的保留关键字不能用作标识符:

and       break     do        else      elseif    end
false     for       function  goto      if        in
local     nil       not       or        repeat    return
then      true      until     while

注意: 这些关键字区分大小写,例如 AndAND 不是关键字,可以作为标识符使用。

# 2.4 变量

Lua 变量是弱类型,不需要声明类型,直接赋值即可。

Lua 变量有三种类型:全局变量、局部变量和表字段。

全局变量:在函数外部定义的变量,可以在函数内部访问。默认情况下,变量总是认为是全局的。

局部变量:在函数内部定义的变量,只能在函数内部访问。

表字段:在表(table)中定义的变量,只能在表内访问。

-- 全局变量
a = 10
b = 20
-- 局部变量
function add()
    local c = a + b
    return c
end
-- 表字段
mytable = {}
mytable.field1 = "Hello"
mytable.field2 = "World"

# 2.5 数据类型

Lua 是动态类型语言,变量不需要类型定义。Lua 支持 8 种基本数据类型:

# 1. nil(空值)

表示空值或无效值,在条件表达式中相当于 false。未初始化的变量默认为 nil。

local a
print(a)        -- 输出:nil
print(type(a))  -- 输出:nil
-- 删除变量(将其设为 nil)
b = 10
b = nil
print(b)        -- 输出:nil

# 2. boolean(布尔值)

只有两个值:true 和 false。在 Lua 中,只有 nil 和 false 为假,其他所有值都为真(包括 0 和空字符串)。

local flag1 = true
local flag2 = false
print(type(flag1))  -- 输出:boolean
-- 条件判断
if 0 then
    print("0是真值")     -- 会执行
end
if "" then
    print("空字符串是真值") -- 会执行
end

# 3. number(数值)

Lua 中的数值类型,可以表示整数和浮点数。在 Lua 5.3 + 中,number 类型分为 integer 和 float 两个子类型。

local int_num = 42
local float_num = 3.14
local exp_num = 1.23e-4
local hex_num = 0xff
print(type(int_num))    -- 输出:number
print(int_num + float_num)  -- 输出:45.14

# 4. string(字符串)

字符串是不可变的值,可以用单引号、双引号或长括号定义。

local str1 = 'Hello'
local str2 = "World"
local str3 = [[
多行字符串
可以包含换行
]]
-- 字符串连接
local result = str1 .. " " .. str2  -- 输出:Hello World
-- 字符串长度
print(#str1)  -- 输出:5

# 5. function(函数)

函数是第一类值,可以赋值给变量,作为参数传递。

-- 函数定义
function greet(name)
    return "Hello, " .. name
end
-- 函数赋值给变量
local sayHello = greet
print(sayHello("Lua"))  -- 输出:Hello, Lua
print(type(greet))      -- 输出:function

# 6. table(表)

Lua 中唯一的数据结构,可以实现数组、字典、对象等。

-- 数组形式
local arr = {1, 2, 3, 4, 5}
print(arr[1])  -- 输出:1(注意:Lua 数组从 1 开始)
-- 字典形式
local dict = {
    name = "张三",
    age = 25,
    city = "北京"
}
print(dict.name)  -- 输出:张三
print(dict["age"])  -- 输出:25
print(type(arr))   -- 输出:table

# 7. userdata(用户数据)

用于存储 C 数据的类型,通常用于 Lua 与 C 程序的交互。

-- userdata 通常由 C 代码创建
-- 这里只是示例,实际使用中由 C API 创建
print(type(io.stdin))  -- 输出:userdata

# 8. thread(线程)

表示协程,用于实现协作式多任务。

-- 创建协程
local co = coroutine.create(function()
    print("协程执行")
end)
print(type(co))  -- 输出:thread

# 类型检查函数

使用 type() 函数可以获取变量的类型:

print(type(nil))        -- nil
print(type(true))       -- boolean
print(type(42))         -- number
print(type("hello"))    -- string
print(type({}))         -- table
print(type(print))      -- function

# 2.6 循环

Lua 提供了多种循环结构来重复执行代码块。

# 1. while 循环

当条件为真时重复执行代码块。

语法:

while condition do
    -- 循环体
end

示例:

local i = 1
while i <= 5 do
    print("第" .. i .. "次循环")
    i = i + 1
end
-- 输出:
-- 第 1 次循环
-- 第 2 次循环
-- 第 3 次循环
-- 第 4 次循环
-- 第 5 次循环

# 2. for 循环

Lua 有两种 for 循环:数值 for 循环和泛型 for 循环。

# 数值 for 循环
-- 语法:for var = start, end, step do
for i = 1, 5 do
    print("i = " .. i)
end
-- 指定步长
for i = 1, 10, 2 do
    print("奇数:" .. i)
end
-- 递减循环
for i = 5, 1, -1 do
    print("倒数:" .. i)
end
# 泛型 for 循环

用于遍历迭代器返回的值。

-- 遍历数组
local fruits = {"苹果", "香蕉", "橙子"}
for index, value in ipairs(fruits) do
    print(index .. ": " .. value)
end
-- 遍历表的键值对
local person = {name = "张三", age = 25, city = "北京"}
for key, value in pairs(person) do
    print(key .. " = " .. value)
end

# 3. repeat-until 循环

先执行循环体,然后检查条件。至少执行一次。

语法:

repeat
    -- 循环体
until condition

示例:

local i = 1
repeat
    print("repeat循环:" .. i)
    i = i + 1
until i > 3
-- 输出:
-- repeat 循环:1
-- repeat 循环:2
-- repeat 循环:3

# 4. 循环嵌套

循环内部可以包含其他循环。

-- 九九乘法表
for i = 1, 9 do
    for j = 1, i do
        io.write(j .. "x" .. i .. "=" .. (i*j) .. "\t")
    end
    print()  -- 换行
end

# 5. 循环控制语句

# break 语句

立即退出当前循环。

for i = 1, 10 do
    if i == 5 then
        break  -- 当 i 等于 5 时退出循环
    end
    print(i)
end
-- 输出:1 2 3 4
# goto 语句(Lua 5.2+)

跳转到指定标签。可以用来模拟 continue 的效果。

for i = 1, 5 do
    if i == 3 then
        goto continue  -- 跳过当前迭代
    end
    print(i)
    ::continue::  -- 标签
end
-- 输出:1 2 4 5

注意: Lua 没有 continue 语句,但可以使用 goto 或者重构代码逻辑来实现类似效果。

# 6. 无限循环

-- 使用 while true
while true do
    local input = io.read()
    if input == "quit" then
        break
    end
    print("你输入了:" .. input)
end
-- 使用 repeat
repeat
    -- 执行某些操作
    local shouldContinue = someCondition()
until not shouldContinue

# 2.7 控制结构语句

Lua 提供了条件控制语句来根据不同条件执行不同的代码块。

# 1. if 语句

最基本的条件语句,当条件为真时执行代码块。

语法:

if condition then
    -- 代码块
end

示例:

local age = 18
if age >= 18 then
    print("已成年")
end
local score = 85
if score >= 60 then
    print("及格了")
end

# 2. if-else 语句

提供两个分支,条件为真执行 if 分支,否则执行 else 分支。

语法:

if condition then
    -- 条件为真时执行
else
    -- 条件为假时执行
end

示例:

local weather = "晴天"
if weather == "晴天" then
    print("今天天气不错,适合出门")
else
    print("今天天气不好,在家休息")
end
local number = 7
if number % 2 == 0 then
    print(number .. "是偶数")
else
    print(number .. "是奇数")
end

# 3. if-elseif-else 语句

多重条件判断,按顺序检查条件。

语法:

if condition1 then
    -- 条件 1 为真时执行
elseif condition2 then
    -- 条件 2 为真时执行
elseif condition3 then
    -- 条件 3 为真时执行
else
    -- 所有条件都为假时执行
end

示例:

local score = 85
if score >= 90 then
    print("优秀")
elseif score >= 80 then
    print("良好")
elseif score >= 70 then
    print("中等")
elseif score >= 60 then
    print("及格")
else
    print("不及格")
end
-- 判断季节
local month = 3
if month >= 3 and month <= 5 then
    print("春季")
elseif month >= 6 and month <= 8 then
    print("夏季")
elseif month >= 9 and month <= 11 then
    print("秋季")
else
    print("冬季")
end

# 4. if 语句嵌套

if 语句内部可以包含其他 if 语句。

local age = 25
local hasLicense = true
if age >= 18 then
    print("已成年")
    if hasLicense then
        print("可以开车")
    else
        print("需要考驾照")
    end
else
    print("未成年,不能开车")
end
-- 复杂嵌套示例
local username = "admin"
local password = "123456"
local isActive = true
if username == "admin" then
    if password == "123456" then
        if isActive then
            print("登录成功")
        else
            print("账户已被禁用")
        end
    else
        print("密码错误")
    end
else
    print("用户名不存在")
end

# 5. 条件表达式的真假值

在 Lua 中,只有 nilfalse 被认为是假值,其他所有值都是真值。

-- 真值示例
if 0 then print("0是真值") end           -- 输出
if "" then print("空字符串是真值") end    -- 输出
if {} then print("空表是真值") end       -- 输出
-- 假值示例
if nil then 
    print("不会输出") 
end
if false then 
    print("不会输出") 
end
-- 实际应用
local value = nil
if value then
    print("value有值:" .. value)
else
    print("value为空")  -- 输出这个
end

# 6. 逻辑运算符在条件中的使用

local age = 25
local income = 5000
-- and 运算符
if age >= 18 and income >= 3000 then
    print("符合贷款条件")
end
-- or 运算符
if age < 18 or age > 65 then
    print("特殊年龄段")
end
-- not 运算符
local isStudent = false
if not isStudent then
    print("不是学生")
end
-- 复合条件
if (age >= 18 and age <= 65) and (income >= 3000 or hasGuarantor) then
    print("可以申请贷款")
end

# 7. 三元运算符的模拟

Lua 没有三元运算符,但可以用 and 和 or 来模拟:

-- 模拟 condition ? value1 : value2
local age = 20
local status = age >= 18 and "成年人" or "未成年人"
print(status)  -- 输出:成年人
-- 注意:当 value1 为假值时,这种方法会有问题
local result = true and false or "default"  -- 结果是 "default" 而不是 false
-- 更安全的方法
local function ternary(condition, trueValue, falseValue)
    if condition then
        return trueValue
    else
        return falseValue
    end
end
local message = ternary(age >= 18, "可以投票", "不能投票")
print(message)

# 2.8 函数

函数是 Lua 中的第一类值,可以赋值给变量、作为参数传递、作为返回值返回。

# 1. 函数定义

Lua 提供了多种定义函数的方式。

# 标准函数定义
function functionName(parameters)
    -- 函数体
    return value  -- 可选的返回值
end
-- 示例
function greet(name)
    return "Hello, " .. name
end
print(greet("World"))  -- 输出:Hello, World
# 匿名函数(函数表达式)
local add = function(a, b)
    return a + b
end
print(add(3, 5))  -- 输出:8
-- 直接使用匿名函数
local result = (function(x) return x * x end)(5)
print(result)  -- 输出:25

# 2. 函数参数

# 固定参数
function multiply(a, b)
    return a * b
end
print(multiply(4, 5))  -- 输出:20
# 可变参数

使用 ... 表示可变参数。

function sum(...)
    local args = {...}  -- 将可变参数打包成表
    local total = 0
    for i = 1, #args do
        total = total + args[i]
    end
    return total
end
print(sum(1, 2, 3, 4, 5))  -- 输出:15
-- 另一种处理可变参数的方式
function printAll(...)
    for i = 1, select("#", ...) do
        local arg = select(i, ...)
        print("参数" .. i .. ": " .. arg)
    end
end
printAll("a", "b", "c")
# 默认参数

Lua 没有内置的默认参数,但可以通过逻辑运算符实现。

function greet(name, greeting)
    name = name or "World"
    greeting = greeting or "Hello"
    return greeting .. ", " .. name
end
print(greet())              -- 输出:Hello, World
print(greet("Lua"))         -- 输出:Hello, Lua
print(greet("Lua", "Hi"))   -- 输出:Hi, Lua

# 3. 函数返回值

# 单个返回值
function square(x)
    return x * x
end
local result = square(4)
print(result)  -- 输出:16
# 多个返回值
function divmod(a, b)
    return math.floor(a / b), a % b
end
local quotient, remainder = divmod(17, 5)
print(quotient, remainder)  -- 输出:3 2
-- 只接收第一个返回值
local q = divmod(17, 5)
print(q)  -- 输出:3
# 返回表
function getPersonInfo()
    return {
        name = "张三",
        age = 25,
        city = "北京"
    }
end
local person = getPersonInfo()
print(person.name)  -- 输出:张三

# 4. 局部函数和全局函数

# 全局函数
function globalFunction()
    print("这是全局函数")
end
globalFunction()  -- 可以在任何地方调用
# 局部函数
local function localFunction()
    print("这是局部函数")
end
localFunction()  -- 只能在定义的作用域内调用
-- 递归局部函数需要先声明
local factorial
factorial = function(n)
    if n <= 1 then
        return 1
    else
        return n * factorial(n - 1)
    end
end
print(factorial(5))  -- 输出:120

# 5. 高阶函数

函数可以作为参数传递给其他函数。

function applyOperation(a, b, operation)
    return operation(a, b)
end
local function add(x, y)
    return x + y
end
local function multiply(x, y)
    return x * y
end
print(applyOperation(3, 4, add))      -- 输出:7
print(applyOperation(3, 4, multiply)) -- 输出:12
-- 使用匿名函数
print(applyOperation(3, 4, function(x, y) return x - y end))  -- 输出:-1

# 6. 闭包

函数可以访问其外部作用域的变量。

function createCounter()
    local count = 0
    return function()
        count = count + 1
        return count
    end
end
local counter1 = createCounter()
local counter2 = createCounter()
print(counter1())  -- 输出:1
print(counter1())  -- 输出:2
print(counter2())  -- 输出:1
print(counter1())  -- 输出:3

# 7. 函数作为表的字段

local math_utils = {
    add = function(a, b) return a + b end,
    subtract = function(a, b) return a - b end,
    multiply = function(a, b) return a * b end
}
print(math_utils.add(5, 3))       -- 输出:8
print(math_utils.subtract(5, 3))  -- 输出:2
-- 方法调用语法糖
local person = {
    name = "张三",
    greet = function(self)
        return "Hello, I'm " .. self.name
    end
}
print(person.greet(person))  -- 输出:Hello, I'm 张三
print(person:greet())        -- 语法糖,等价于上面的调用

# 8. 尾调用优化

Lua 支持尾调用优化,可以避免栈溢出。

-- 非尾调用(会消耗栈空间)
function factorial_bad(n)
    if n <= 1 then
        return 1
    else
        return n * factorial_bad(n - 1)  -- 不是尾调用
    end
end
-- 尾调用版本
function factorial_good(n, acc)
    acc = acc or 1
    if n <= 1 then
        return acc
    else
        return factorial_good(n - 1, n * acc)  -- 尾调用
    end
end
print(factorial_good(5))  -- 输出:120

# 9. 函数的一些内置函数

-- 获取函数信息
function testFunc() end
print(type(testFunc))  -- 输出:function
-- 使用 pcall 进行安全调用
function riskyFunction(x)
    if x < 0 then
        error("x不能为负数")
    end
    return x * 2
end
local success, result = pcall(riskyFunction, 5)
if success then
    print("结果:" .. result)  -- 输出:结果:10
else
    print("错误:" .. result)
end
local success, result = pcall(riskyFunction, -1)
if success then
    print("结果:" .. result)
else
    print("错误:" .. result)  -- 输出错误信息
end

# 2.9 运算符

Lua 提供了多种运算符用于执行各种操作。

# 1. 算术运算符

用于执行数学运算。

运算符 描述 示例 结果
+ 加法 5 + 3 8
- 减法 5 - 3 2
* 乘法 5 * 3 15
/ 除法 10 / 3 3.333...
// 整除 10 // 3 3
% 取模 10 % 3 1
^ 幂运算 2 ^ 3 8
- 负号 -5 -5
local a = 10
local b = 3
print(a + b)   -- 输出:13
print(a - b)   -- 输出:7
print(a * b)   -- 输出:30
print(a / b)   -- 输出:3.3333333333333
print(a // b)  -- 输出:3 (整除,Lua 5.3+)
print(a % b)   -- 输出:1
print(a ^ b)   -- 输出:1000
print(-a)      -- 输出:-10
-- 复合运算
local result = (a + b) * 2 - a / b
print(result)  -- 输出:22.666666666667

# 2. 关系运算符

用于比较两个值,返回布尔值。

运算符 描述 示例 结果
== 等于 5 == 5 true
~= 不等于 5 ~= 3 true
< 小于 3 < 5 true
> 大于 5 > 3 true
<= 小于等于 3 <= 5 true
>= 大于等于 5 >= 5 true
local x = 10
local y = 20
print(x == y)   -- 输出:false
print(x ~= y)   -- 输出:true
print(x < y)    -- 输出:true
print(x > y)    -- 输出:false
print(x <= y)   -- 输出:true
print(x >= y)   -- 输出:false
-- 字符串比较
local str1 = "apple"
local str2 = "banana"
print(str1 < str2)  -- 输出:true (按字典序)
-- 注意:不同类型的比较
print(10 == "10")   -- 输出:false (类型不同)
print(nil == false) -- 输出:false

# 3. 逻辑运算符

用于逻辑运算,具有短路求值特性。

运算符 描述 示例
and 逻辑与 a and b
or 逻辑或 a or b
not 逻辑非 not a
local a = true
local b = false
local c = nil
print(a and b)      -- 输出:false
print(a or b)       -- 输出:true
print(not a)        -- 输出:false
print(not b)        -- 输出:true
-- 短路求值
print(false and print("不会执行"))  -- 输出:false,print 不会执行
print(true or print("不会执行"))    -- 输出:true,print 不会执行
-- 实际应用:设置默认值
local name = nil
local defaultName = name or "匿名用户"
print(defaultName)  -- 输出:匿名用户
-- 条件执行
local age = 25
age >= 18 and print("成年人")  -- 输出:成年人
-- 复合逻辑
local score = 85
local passed = score >= 60 and score < 100
print(passed)  -- 输出:true

# 4. 其他运算符

# 字符串连接运算符 (..)
local firstName = "张"
local lastName = "三"
local fullName = firstName .. lastName
print(fullName)  -- 输出:张三
-- 数字会自动转换为字符串
local age = 25
local message = "我今年" .. age .. "岁"
print(message)  -- 输出:我今年 25 岁
-- 多个连接
local result = "a" .. "b" .. "c" .. "d"
print(result)  -- 输出:abcd
# 长度运算符 (#)
-- 字符串长度
local str = "Hello"
print(#str)  -- 输出:5
-- 表长度(数组部分)
local arr = {1, 2, 3, 4, 5}
print(#arr)  -- 输出:5
-- 注意:对于有空洞的数组,结果可能不准确
local sparse = {1, 2, nil, 4, 5}
print(#sparse)  -- 结果不确定
-- 中文字符串长度(字节数)
local chinese = "你好"
print(#chinese)  -- 输出:6 (UTF-8 编码,每个中文字符 3 字节)

# 5. 运算符优先级

从高到低的优先级顺序:

  1. ^ (幂运算)
  2. not # - (一元运算符)
  3. * / // %
  4. + -
  5. .. (字符串连接)
  6. < > <= >= ~= ==
  7. and
  8. or
-- 优先级示例
local result1 = 2 + 3 * 4      -- 等价于 2 + (3 * 4) = 14
local result2 = 2 ^ 3 * 4      -- 等价于 (2 ^ 3) * 4 = 32
local result3 = not false or true and false  -- 等价于 (not false) or (true and false) = true
print(result1)  -- 输出:14
print(result2)  -- 输出:32
print(result3)  -- 输出:true
-- 使用括号改变优先级
local result4 = (2 + 3) * 4    -- 等价于 5 * 4 = 20
print(result4)  -- 输出:20

# 6. 类型转换

Lua 在某些运算中会自动进行类型转换。

-- 字符串到数字的转换
print("10" + 5)     -- 输出:15
print("3.14" * 2)   -- 输出:6.28
-- 数字到字符串的转换
print(10 .. 20)     -- 输出:1020
-- 无法转换时会报错
-- print ("hello" + 5)  -- 错误:attempt to perform arithmetic on a string value
-- 显式转换
local str = "123"
local num = tonumber(str)
print(num + 10)     -- 输出:133
local number = 456
local string = tostring(number)
print(string .. "789")  -- 输出:456789

# 7. 比较运算的特殊情况

-- 表的比较(引用比较)
local t1 = {1, 2, 3}
local t2 = {1, 2, 3}
local t3 = t1
print(t1 == t2)  -- 输出:false (不同的表对象)
print(t1 == t3)  -- 输出:true (相同的引用)
-- 函数的比较
local function f1() end
local function f2() end
local f3 = f1
print(f1 == f2)  -- 输出:false
print(f1 == f3)  -- 输出:true
-- NaN 的比较
local nan = 0/0
print(nan == nan)  -- 输出:false (NaN 不等于任何值,包括自己)

# 2.10 字符串

字符串是 Lua 中的基本数据类型之一,用于表示文本数据。Lua 中的字符串是不可变的。

# 1. 字符串定义

Lua 提供了多种定义字符串的方式。

# 单引号和双引号
local str1 = 'Hello World'
local str2 = "Hello World"
local str3 = 'He said "Hello"'  -- 单引号内可以包含双引号
local str4 = "It's a beautiful day"  -- 双引号内可以包含单引号
print(str1)  -- 输出:Hello World
print(str2)  -- 输出:Hello World
print(str3)  -- 输出:He said "Hello"
print(str4)  -- 输出:It's a beautiful day
# 长字符串(多行字符串)

使用 [[]] 定义多行字符串,可以包含换行符。

local multiline = [[
这是一个多行字符串
可以包含换行符
不需要转义引号 "和'
]]
print(multiline)
-- 嵌套长字符串
local nested = [=[
这个字符串可以包含 [[其他长字符串]]
使用不同数量的等号来区分嵌套层级
]=]
print(nested)

# 2. 转义字符

在字符串中使用反斜杠 \ 来表示特殊字符。

转义序列 含义
\a 响铃
\b 退格
\f 换页
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\ 反斜杠
" 双引号
' 单引号
\0 空字符
local str = "第一行\n第二行\t制表符\\"反斜杠\\""
print(str)
-- 输出:
-- 第一行
-- 第二行	制表符 "反斜杠"
-- 使用数字转义
local str2 = "\65\66\67"  -- ASCII 码
print(str2)  -- 输出:ABC

# 3. 字符串连接

使用 .. 运算符连接字符串。

local first = "Hello"
local second = "World"
local result = first .. " " .. second
print(result)  -- 输出:Hello World
-- 数字会自动转换为字符串
local age = 25
local message = "我今年" .. age .. "岁"
print(message)  -- 输出:我今年 25 岁
-- 连续连接
local path = "home" .. "/" .. "user" .. "/" .. "documents"
print(path)  -- 输出:home/user/documents

# 4. 字符串长度

使用 # 运算符获取字符串长度(字节数)。

local str = "Hello"
print(#str)  -- 输出:5
local chinese = "你好"
print(#chinese)  -- 输出:6 (UTF-8 编码,每个中文字符 3 字节)
-- 空字符串
local empty = ""
print(#empty)  -- 输出:0

# 5. 字符串库函数

Lua 提供了丰富的字符串处理函数。

# 大小写转换
local str = "Hello World"
print(string.upper(str))  -- 输出:HELLO WORLD
print(string.lower(str))  -- 输出:hello world
-- 简化写法
print(str:upper())  -- 输出:HELLO WORLD
print(str:lower())  -- 输出:hello world
# 字符串查找
local text = "Hello Lua World"
-- 查找子字符串
local start, finish = string.find(text, "Lua")
print(start, finish)  -- 输出:7 9
-- 简化写法
local start, finish = text:find("World")
print(start, finish)  -- 输出:11 15
-- 查找不存在的子字符串
local pos = text:find("Python")
print(pos)  -- 输出:nil
# 字符串替换
local text = "Hello World, Hello Lua"
-- 替换第一个匹配项
local result1 = string.gsub(text, "Hello", "Hi", 1)
print(result1)  -- 输出:Hi World, Hello Lua
-- 替换所有匹配项
local result2 = string.gsub(text, "Hello", "Hi")
print(result2)  -- 输出:Hi World, Hi Lua
-- 简化写法
local result3 = text:gsub("Hello", "Greetings")
print(result3)  -- 输出:Greetings World, Greetings Lua
# 字符串截取
local text = "Hello World"
-- 截取子字符串
local sub1 = string.sub(text, 1, 5)   -- 从位置 1 到 5
print(sub1)  -- 输出:Hello
local sub2 = string.sub(text, 7)      -- 从位置 7 到末尾
print(sub2)  -- 输出:World
local sub3 = string.sub(text, -5)     -- 从倒数第 5 个字符到末尾
print(sub3)  -- 输出:World
-- 简化写法
local sub4 = text:sub(1, 5)
print(sub4)  -- 输出:Hello
# 字符串分割
-- 简单分割函数
function split(str, delimiter)
    local result = {}
    local pattern = "([^" .. delimiter .. "]+)"
    for match in str:gmatch(pattern) do
        table.insert(result, match)
    end
    return result
end
local text = "apple,banana,orange"
local fruits = split(text, ",")
for i, fruit in ipairs(fruits) do
    print(i, fruit)
end
-- 输出:
-- 1	apple
-- 2	banana
-- 3	orange
# 字符串格式化
-- 使用 string.format 进行格式化
local name = "张三"
local age = 25
local score = 85.5
local message = string.format("姓名:%s,年龄:%d,分数:%.1f", name, age, score)
print(message)  -- 输出:姓名:张三,年龄:25,分数:85.5
-- 常用格式化符号
print(string.format("%d", 42))        -- 整数:42
print(string.format("%.2f", 3.14159)) -- 浮点数:3.14
print(string.format("%s", "hello"))   -- 字符串:hello
print(string.format("%x", 255))       -- 十六进制:ff
print(string.format("%o", 8))         -- 八进制:10
# 字符串匹配和模式
local text = "The price is $123.45"
-- 简单匹配
local number = text:match("%d+")  -- 匹配数字
print(number)  -- 输出:123
-- 匹配浮点数
local price = text:match("%d+%.%d+")
print(price)  -- 输出:123.45
-- 匹配所有数字
for num in text:gmatch("%d+") do
    print(num)
end
-- 输出:123 45
-- 常用模式
local email = "user@example.com"
local username = email:match("([^@]+)")  -- 匹配 @之前的部分
print(username)  -- 输出:user

# 6. 字符串模式匹配字符

Lua 使用特殊的模式匹配字符:

字符 含义
. 匹配任意字符
%a 匹配字母
%d 匹配数字
%l 匹配小写字母
%u 匹配大写字母
%w 匹配字母和数字
%s 匹配空白字符
%p 匹配标点符号
%c 匹配控制字符
%x 匹配十六进制数字
+ 匹配一个或多个
* 匹配零个或多个
- 匹配零个或多个(非贪婪)
? 匹配零个或一个
local text = "Hello123 World456"
-- 匹配字母
for word in text:gmatch("%a+") do
    print(word)
end
-- 输出:Hello World
-- 匹配数字
for num in text:gmatch("%d+") do
    print(num)
end
-- 输出:123 456
-- 匹配字母和数字
for item in text:gmatch("%w+") do
    print(item)
end
-- 输出:Hello123 World456

# 7. 字符串和数字的转换

-- 字符串转数字
local str_num = "123"
local num = tonumber(str_num)
print(num + 10)  -- 输出:133
-- 处理转换失败
local invalid = "abc"
local result = tonumber(invalid)
print(result)  -- 输出:nil
-- 数字转字符串
local number = 456
local str = tostring(number)
print(str .. "789")  -- 输出:456789
-- 自动转换
print("10" + 5)    -- 输出:15 (字符串自动转为数字)
print(10 .. 20)    -- 输出:1020 (数字自动转为字符串)

# 8. 实用字符串处理示例

-- 去除字符串两端空白
function trim(str)
    return str:match("^%s*(.-)%s*$")
end
local text = "  Hello World  "
print("'" .. trim(text) .. "'")  -- 输出:'Hello World'
-- 检查字符串是否为空
function isEmpty(str)
    return str == nil or str == "" or str:match("^%s*$") ~= nil
end
print(isEmpty(""))      -- 输出:true
print(isEmpty("  "))    -- 输出:true
print(isEmpty("hello")) -- 输出:false
-- 首字母大写
function capitalize(str)
    return str:sub(1, 1):upper() .. str:sub(2):lower()
end
print(capitalize("hello"))  -- 输出:Hello
print(capitalize("WORLD"))  -- 输出:World

# 2.11 数组

在 Lua 中,数组实际上是表(table)的一种特殊形式,使用连续的整数作为索引。Lua 的数组索引从 1 开始,这与许多其他编程语言不同。

# 1. 数组的创建

# 直接初始化
-- 创建数组
local fruits = {"苹果", "香蕉", "橙子", "葡萄"}
local numbers = {10, 20, 30, 40, 50}
local mixed = {1, "hello", true, 3.14}
-- 访问数组元素
print(fruits[1])    -- 输出:苹果
print(numbers[3])   -- 输出:30
print(mixed[2])     -- 输出:hello
# 动态创建
-- 创建空数组
local arr = {}
-- 添加元素
arr[1] = "第一个元素"
arr[2] = "第二个元素"
arr[3] = "第三个元素"
-- 或者使用 table.insert
local list = {}
table.insert(list, "元素1")
table.insert(list, "元素2")
table.insert(list, "元素3")
print(list[1])  -- 输出:元素 1

# 2. 数组长度

使用 # 运算符获取数组长度。

local arr = {10, 20, 30, 40, 50}
print(#arr)  -- 输出:5
-- 空数组
local empty = {}
print(#empty)  -- 输出:0
-- 注意:有空洞的数组长度可能不准确
local sparse = {1, 2, nil, 4, 5}
print(#sparse)  -- 结果不确定,可能是 2 或 5

# 3. 数组遍历

# 使用数值 for 循环
local fruits = {"苹果", "香蕉", "橙子", "葡萄"}
for i = 1, #fruits do
    print(i, fruits[i])
end
-- 输出:
-- 1	苹果
-- 2	香蕉
-- 3	橙子
-- 4	葡萄
# 使用 ipairs 迭代器
local numbers = {10, 20, 30, 40, 50}
for index, value in ipairs(numbers) do
    print(index, value)
end
-- 输出:
-- 1	10
-- 2	20
-- 3	30
-- 4	40
-- 5	50
# ipairs vs pairs
local arr = {10, 20, nil, 40, 50}
print("使用ipairs:")
for i, v in ipairs(arr) do
    print(i, v)
end
-- 输出:1 10, 2 20 (遇到 nil 停止)
print("使用pairs:")
for i, v in pairs(arr) do
    print(i, v)
end
-- 输出:1 10, 2 20, 4 40, 5 50 (跳过 nil)

# 4. 数组操作

# 添加元素
local arr = {1, 2, 3}
-- 在末尾添加
table.insert(arr, 4)
print(table.concat(arr, ", "))  -- 输出:1, 2, 3, 4
-- 在指定位置插入
table.insert(arr, 2, "插入的元素")
print(table.concat(arr, ", "))  -- 输出:1, 插入的元素,2, 3, 4
-- 直接赋值
arr[#arr + 1] = 5
print(table.concat(arr, ", "))  -- 输出:1, 插入的元素,2, 3, 4, 5
# 删除元素
local arr = {"a", "b", "c", "d", "e"}
-- 删除末尾元素
local removed = table.remove(arr)
print("删除的元素:", removed)  -- 输出:删除的元素: e
print(table.concat(arr, ", "))  -- 输出:a, b, c, d
-- 删除指定位置的元素
local removed2 = table.remove(arr, 2)
print("删除的元素:", removed2)  -- 输出:删除的元素: b
print(table.concat(arr, ", "))  -- 输出:a, c, d
-- 设置为 nil(不推荐,会产生空洞)
arr[2] = nil
print("长度:", #arr)  -- 长度可能不准确
# 数组连接
local arr = {"苹果", "香蕉", "橙子"}
-- 连接成字符串
local str1 = table.concat(arr)
print(str1)  -- 输出:苹果香蕉橙子
-- 使用分隔符连接
local str2 = table.concat(arr, ", ")
print(str2)  -- 输出:苹果,香蕉,橙子
-- 指定范围连接
local str3 = table.concat(arr, " | ", 1, 2)
print(str3)  -- 输出:苹果 | 香蕉

# 5. 数组排序

local numbers = {5, 2, 8, 1, 9, 3}
-- 默认升序排序
table.sort(numbers)
print(table.concat(numbers, ", "))  -- 输出:1, 2, 3, 5, 8, 9
-- 自定义排序(降序)
local numbers2 = {5, 2, 8, 1, 9, 3}
table.sort(numbers2, function(a, b) return a > b end)
print(table.concat(numbers2, ", "))  -- 输出:9, 8, 5, 3, 2, 1
-- 字符串排序
local fruits = {"香蕉", "苹果", "橙子", "葡萄"}
table.sort(fruits)
print(table.concat(fruits, ", "))  -- 按字典序排序

# 6. 多维数组

-- 创建二维数组
local matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
}
-- 访问元素
print(matrix[2][3])  -- 输出:6
-- 遍历二维数组
for i = 1, #matrix do
    for j = 1, #matrix[i] do
        io.write(matrix[i][j] .. " ")
    end
    print()  -- 换行
end
-- 输出:
-- 1 2 3 
-- 4 5 6 
-- 7 8 9 
-- 动态创建二维数组
local rows, cols = 3, 4
local arr2d = {}
for i = 1, rows do
    arr2d[i] = {}
    for j = 1, cols do
        arr2d[i][j] = i * cols + j - cols
    end
end
-- 打印结果
for i = 1, rows do
    print(table.concat(arr2d[i], " "))
end

# 7. 数组的实用函数

-- 查找元素
function findElement(arr, target)
    for i, v in ipairs(arr) do
        if v == target then
            return i
        end
    end
    return nil
end
local fruits = {"苹果", "香蕉", "橙子"}
local index = findElement(fruits, "香蕉")
print("香蕉的索引:", index)  -- 输出:香蕉的索引: 2
-- 数组反转
function reverseArray(arr)
    local reversed = {}
    for i = #arr, 1, -1 do
        table.insert(reversed, arr[i])
    end
    return reversed
end
local numbers = {1, 2, 3, 4, 5}
local reversed = reverseArray(numbers)
print(table.concat(reversed, ", "))  -- 输出:5, 4, 3, 2, 1
-- 数组去重
function removeDuplicates(arr)
    local seen = {}
    local result = {}
    for _, v in ipairs(arr) do
        if not seen[v] then
            seen[v] = true
            table.insert(result, v)
        end
    end
    return result
end
local withDuplicates = {1, 2, 2, 3, 1, 4, 3, 5}
local unique = removeDuplicates(withDuplicates)
print(table.concat(unique, ", "))  -- 输出:1, 2, 3, 4, 5
-- 数组过滤
function filterArray(arr, predicate)
    local result = {}
    for _, v in ipairs(arr) do
        if predicate(v) then
            table.insert(result, v)
        end
    end
    return result
end
local numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
local evens = filterArray(numbers, function(x) return x % 2 == 0 end)
print("偶数:", table.concat(evens, ", "))  -- 输出:偶数: 2, 4, 6, 8, 10
-- 数组映射
function mapArray(arr, transform)
    local result = {}
    for _, v in ipairs(arr) do
        table.insert(result, transform(v))
    end
    return result
end
local numbers = {1, 2, 3, 4, 5}
local squares = mapArray(numbers, function(x) return x * x end)
print("平方:", table.concat(squares, ", "))  -- 输出:平方: 1, 4, 9, 16, 25

# 8. 数组与字符串的转换

-- 字符串分割成数组
function split(str, delimiter)
    local result = {}
    local pattern = "([^" .. delimiter .. "]+)"
    for match in str:gmatch(pattern) do
        table.insert(result, match)
    end
    return result
end
local text = "apple,banana,orange"
local fruits = split(text, ",")
print("分割结果:", table.concat(fruits, " | "))
-- 数组合并成字符串
local words = {"Hello", "World", "from", "Lua"}
local sentence = table.concat(words, " ")
print(sentence)  -- 输出:Hello World from Lua

# 9. 数组的注意事项

-- 1. 索引从 1 开始
local arr = {"a", "b", "c"}
print(arr[0])  -- 输出:nil
print(arr[1])  -- 输出:a
-- 2. 稀疏数组的长度问题
local sparse = {}
sparse[1] = "first"
sparse[5] = "fifth"
sparse[10] = "tenth"
print("长度:", #sparse)  -- 可能不是 10
-- 3. 混合索引的表
local mixed = {
    "first",    -- 索引 1
    "second",   -- 索引 2
    name = "张三",  -- 字符串索引
    age = 25    -- 字符串索引
}
print("数组长度:", #mixed)  -- 输出:2
print("姓名:", mixed.name)  -- 输出:姓名:张三
-- 4. 数组复制(浅拷贝)
local original = {1, 2, 3, {4, 5}}
local copy = {}
for i, v in ipairs(original) do
    copy[i] = v
end
-- 注意:嵌套的表仍然是引用

# 2.12 迭代器

迭代器是 Lua 中用于遍历数据集合的重要机制。Lua 提供了内置的迭代器,也允许用户自定义迭代器。

# 1. 内置迭代器

# ipairs 迭代器

用于遍历数组(连续整数索引的表)。

local fruits = {"苹果", "香蕉", "橙子", "葡萄"}
for index, value in ipairs(fruits) do
    print(index .. ": " .. value)
end
-- 输出:
-- 1: 苹果
-- 2: 香蕉
-- 3: 橙子
-- 4: 葡萄
-- 遇到 nil 会停止
local arr = {1, 2, nil, 4, 5}
for i, v in ipairs(arr) do
    print(i, v)
end
-- 输出:1 1, 2 2 (遇到 nil 停止)
# pairs 迭代器

用于遍历表的所有键值对。

local person = {
    name = "张三",
    age = 25,
    city = "北京",
    [1] = "first",
    [2] = "second"
}
for key, value in pairs(person) do
    print(key .. " = " .. tostring(value))
end
-- 输出顺序不确定,但会包含所有键值对
# 字符串迭代器

使用 string.gmatch 进行字符串模式匹配迭代。

local text = "Hello World Lua Programming"
-- 按单词迭代
for word in text:gmatch("%S+") do
    print(word)
end
-- 输出:Hello World Lua Programming
-- 按字符迭代
for char in text:gmatch(".") do
    print(char)
end
-- 匹配数字
local numbers = "123 456 789"
for num in numbers:gmatch("%d+") do
    print("找到数字: " .. num)
end

# 2. 自定义迭代器

# 无状态迭代器

迭代器函数不保存状态,每次调用都重新计算。

-- 平方数迭代器
function squareIterator(max)
    local i = 0
    return function()
        i = i + 1
        if i <= max then
            return i, i * i
        end
    end
end
for index, square in squareIterator(5) do
    print(index .. "^2 = " .. square)
end
-- 输出:
-- 1^2 = 1
-- 2^2 = 4
-- 3^2 = 9
-- 4^2 = 16
-- 5^2 = 25
# 有状态迭代器

使用闭包保存迭代状态。

-- 斐波那契数列迭代器
function fibonacciIterator(max)
    local a, b = 0, 1
    local count = 0
    return function()
        if count < max then
            count = count + 1
            local result = a
            a, b = b, a + b
            return count, result
        end
    end
end
for i, fib in fibonacciIterator(10) do
    print("F(" .. i .. ") = " .. fib)
end

# 3. 复杂迭代器示例

# 文件行迭代器
function lines(filename)
    local file = io.open(filename, "r")
    if not file then
        return function() return nil end
    end
    
    return function()
        local line = file:read("*line")
        if line then
            return line
        else
            file:close()
            return nil
        end
    end
end
-- 使用示例(假设有文件 test.txt)
-- for line in lines("test.txt") do
--     print(line)
-- end
# 目录遍历迭代器
-- 模拟目录遍历(实际需要系统调用)
function directoryIterator(path)
    local files = {"file1.txt", "file2.txt", "dir1"}
    local i = 0
    return function()
        i = i + 1
        if i <= #files then
            return files[i]
        end
    end
end
for file in directoryIterator("/path/to/dir") do
    print("发现文件: " .. file)
end

# 4. 迭代器的实际应用

# 数据库结果集迭代
-- 模拟数据库查询结果
function queryResults(sql)
    -- 模拟数据库结果
    local results = {
        {id = 1, name = "张三", age = 25},
        {id = 2, name = "李四", age = 30},
        {id = 3, name = "王五", age = 28}
    }
    local i = 0
    return function()
        i = i + 1
        if i <= #results then
            return results[i]
        end
    end
end
for row in queryResults("SELECT * FROM users") do
    print("ID: " .. row.id .. ", 姓名: " .. row.name .. ", 年龄: " .. row.age)
end
# 网络数据流迭代
-- 模拟网络数据包迭代
function packetIterator(connection)
    local packets = {"packet1", "packet2", "packet3", "packet4"}
    local i = 0
    return function()
        i = i + 1
        if i <= #packets then
            return packets[i]
        end
    end
end
for packet in packetIterator(nil) do
    print("收到数据包: " .. packet)
end

# 5. 迭代器的性能考虑

# 内存效率
-- 低效:一次性加载所有数据
function inefficientIterator()
    local data = {}
    for i = 1, 1000000 do
        table.insert(data, i)
    end
    local i = 0
    return function()
        i = i + 1
        if i <= #data then
            return data[i]
        end
    end
end
-- 高效:按需生成数据
function efficientIterator(max)
    local i = 0
    return function()
        i = i + 1
        if i <= max then
            return i
        end
    end
end
# 错误处理
function safeIterator(data)
    local i = 0
    return function()
        i = i + 1
        if i <= #data then
            local success, result = pcall(function()
                return data[i]
            end)
            if success then
                return result
            else
                print("迭代器错误: " .. result)
                return nil
            end
        end
    end
end

# 2.13 table 表

表(table)是 Lua 中唯一的数据结构,它既可以作为数组使用,也可以作为字典使用,还可以实现面向对象编程。

# 1. 表的创建和基本操作

# 创建表
-- 空表
local empty_table = {}
-- 数组形式的表
local array = {1, 2, 3, 4, 5}
-- 字典形式的表
local dict = {
    name = "张三",
    age = 25,
    city = "北京"
}
-- 混合形式的表
local mixed = {
    "first",     -- 索引 1
    "second",    -- 索引 2
    name = "张三", -- 字符串键
    age = 25     -- 字符串键
}
# 访问表元素
local person = {
    name = "张三",
    age = 25,
    city = "北京"
}
-- 点语法
print(person.name)    -- 输出:张三
-- 方括号语法
print(person["age"])  -- 输出:25
print(person[1])      -- 输出:nil(没有数字索引)
-- 动态键
local key = "name"
print(person[key])    -- 输出:张三
# 修改表元素
local person = {
    name = "张三",
    age = 25
}
-- 修改现有元素
person.age = 26
person["city"] = "上海"
-- 添加新元素
person.job = "程序员"
person["salary"] = 8000
print(person.name, person.age, person.city, person.job, person.salary)

# 2. 表的遍历

# 遍历所有键值对
local person = {
    name = "张三",
    age = 25,
    city = "北京",
    job = "程序员"
}
-- 使用 pairs
for key, value in pairs(person) do
    print(key .. " = " .. tostring(value))
end
-- 使用 next 函数
local key, value = next(person)
while key do
    print(key .. " = " .. tostring(value))
    key, value = next(person, key)
end
# 遍历数组部分
local arr = {10, 20, 30, 40, 50}
-- 使用 ipairs
for index, value in ipairs(arr) do
    print(index .. ": " .. value)
end
-- 使用数值 for 循环
for i = 1, #arr do
    print(i .. ": " .. arr[i])
end

# 3. 表的操作函数

# table.insert
local fruits = {"苹果", "香蕉"}
-- 在末尾插入
table.insert(fruits, "橙子")
print(table.concat(fruits, ", "))  -- 输出:苹果,香蕉,橙子
-- 在指定位置插入
table.insert(fruits, 2, "葡萄")
print(table.concat(fruits, ", "))  -- 输出:苹果,葡萄,香蕉,橙子
# table.remove
local numbers = {1, 2, 3, 4, 5}
-- 删除末尾元素
local removed = table.remove(numbers)
print("删除的元素:", removed)  -- 输出:删除的元素: 5
print(table.concat(numbers, ", "))  -- 输出:1, 2, 3, 4
-- 删除指定位置的元素
local removed2 = table.remove(numbers, 2)
print("删除的元素:", removed2)  -- 输出:删除的元素: 2
print(table.concat(numbers, ", "))  -- 输出:1, 3, 4
# table.concat
local words = {"Hello", "World", "from", "Lua"}
-- 连接成字符串
local sentence = table.concat(words, " ")
print(sentence)  -- 输出:Hello World from Lua
-- 指定范围连接
local partial = table.concat(words, " | ", 2, 3)
print(partial)  -- 输出:World | from
# table.sort
local numbers = {5, 2, 8, 1, 9, 3}
-- 默认升序排序
table.sort(numbers)
print(table.concat(numbers, ", "))  -- 输出:1, 2, 3, 5, 8, 9
-- 自定义排序函数
table.sort(numbers, function(a, b) return a > b end)
print(table.concat(numbers, ", "))  -- 输出:9, 8, 5, 3, 2, 1
-- 字符串排序
local names = {"张三", "李四", "王五", "赵六"}
table.sort(names)
print(table.concat(names, ", "))

# 4. 表的复制

# 浅拷贝
local original = {1, 2, 3, {4, 5}}
local copy = {}
-- 手动浅拷贝
for key, value in pairs(original) do
    copy[key] = value
end
-- 或者使用 table.move(Lua 5.3+)
local copy2 = {}
table.move(original, 1, #original, 1, copy2)
print(copy[1], copy[4][1])  -- 输出:1, 4
copy[4][1] = 10
print(original[4][1])  -- 输出:10(影响原表)
# 深拷贝
function deepCopy(original)
    if type(original) ~= "table" then
        return original
    end
    
    local copy = {}
    for key, value in pairs(original) do
        copy[deepCopy(key)] = deepCopy(value)
    end
    return copy
end
local original = {1, 2, {3, 4}}
local deepCopy = deepCopy(original)
deepCopy[3][1] = 10
print(original[3][1])  -- 输出:3(不影响原表)

# 5. 表的高级用法

# 实现集合
local set = {}
-- 添加元素
function addToSet(set, element)
    set[element] = true
end
-- 检查元素是否存在
function isInSet(set, element)
    return set[element] == true
end
-- 移除元素
function removeFromSet(set, element)
    set[element] = nil
end
-- 使用示例
addToSet(set, "apple")
addToSet(set, "banana")
print(isInSet(set, "apple"))   -- 输出:true
print(isInSet(set, "orange"))  -- 输出:false
# 实现队列
local queue = {}
function enqueue(queue, value)
    table.insert(queue, value)
end
function dequeue(queue)
    if #queue > 0 then
        return table.remove(queue, 1)
    end
    return nil
end
function peek(queue)
    if #queue > 0 then
        return queue[1]
    end
    return nil
end
-- 使用示例
enqueue(queue, "first")
enqueue(queue, "second")
enqueue(queue, "third")
print(dequeue(queue))  -- 输出:first
print(peek(queue))     -- 输出:second
# 实现栈
local stack = {}
function push(stack, value)
    table.insert(stack, value)
end
function pop(stack)
    if #stack > 0 then
        return table.remove(stack)
    end
    return nil
end
function top(stack)
    if #stack > 0 then
        return stack[#stack]
    end
    return nil
end
-- 使用示例
push(stack, 1)
push(stack, 2)
push(stack, 3)
print(pop(stack))  -- 输出:3
print(top(stack))  -- 输出:2

# 6. 表的元表(metatable)

-- 创建元表
local mt = {
    __index = function(t, k)
        return "默认值"
    end,
    __newindex = function(t, k, v)
        rawset(t, k, v * 2)  -- 存储值的两倍
    end
}
local t = {}
setmetatable(t, mt)
print(t.nonexistent)  -- 输出:默认值
t.x = 5
print(t.x)  -- 输出:10

# 7. 表的性能考虑

# 预分配大小
-- 低效:频繁重新分配
local arr = {}
for i = 1, 10000 do
    table.insert(arr, i)
end
-- 高效:预分配空间
local arr2 = {}
for i = 1, 10000 do
    arr2[i] = i
end
# 避免频繁的 table.insert
-- 低效:频繁插入
local result = {}
for i = 1, 1000 do
    table.insert(result, i)
end
-- 高效:直接赋值
local result2 = {}
for i = 1, 1000 do
    result2[i] = i
end

# 2.14 元表和元方法

元表(metatable)是 Lua 中一个强大的特性,它允许我们修改表的行为。通过元表,我们可以实现面向对象编程、运算符重载等功能。

# 1. 元表的基本概念

# 设置和获取元表
local t = {}
local mt = {}
-- 设置元表
setmetatable(t, mt)
-- 获取元表
local retrieved_mt = getmetatable(t)
print(retrieved_mt == mt)  -- 输出:true
-- 检查是否有元表
if getmetatable(t) then
    print("表有元表")
end
# 元表的保护
local t = {}
local mt = {}
-- 设置元表
setmetatable(t, mt)
-- 保护元表(防止被修改)
mt.__metatable = "受保护的元表"
-- 尝试设置新的元表会失败
local success = pcall(function()
    setmetatable(t, {})
end)
print(success)  -- 输出:false

# 2. __index 元方法

# 处理不存在的键
local t = {a = 1, b = 2}
local mt = {
    __index = function(table, key)
        return "键 '" .. key .. "' 不存在"
    end
}
setmetatable(t, mt)
print(t.a)      -- 输出:1
print(t.c)      -- 输出:键 'c' 不存在
print(t["d"])   -- 输出:键 'd' 不存在
# 继承机制
-- 父表
local parent = {
    name = "父对象",
    sayHello = function(self)
        return "Hello from " .. self.name
    end
}
-- 子表
local child = {
    name = "子对象"
}
-- 设置继承关系
setmetatable(child, {__index = parent})
print(child.name)        -- 输出:子对象
print(child.sayHello(child))  -- 输出:Hello from 子对象
print(child.nonexistent) -- 输出:nil(父表中也没有)
# 默认值表
local defaults = {
    width = 100,
    height = 200,
    color = "black"
}
local mt = {
    __index = defaults
}
local config1 = {}
setmetatable(config1, mt)
config1.width = 150
local config2 = {}
setmetatable(config2, mt)
print(config1.width)   -- 输出:150
print(config1.height)  -- 输出:200
print(config2.width)   -- 输出:100

# 3. __newindex 元方法

# 控制赋值行为
local t = {}
local mt = {
    __newindex = function(table, key, value)
        print("尝试设置 " .. key .. " = " .. tostring(value))
        -- 不执行实际赋值
    end
}
setmetatable(t, mt)
t.x = 10  -- 输出:尝试设置 x = 10
print(t.x)  -- 输出:nil
# 只读表
local readOnly = {a = 1, b = 2}
local mt = {
    __newindex = function(table, key, value)
        error("表是只读的,不能修改键: " .. key)
    end
}
setmetatable(readOnly, mt)
print(readOnly.a)  -- 输出:1
-- readOnly.c = 3  -- 错误:表是只读的,不能修改键: c
# 数据验证
local user = {}
local mt = {
    __newindex = function(table, key, value)
        if key == "age" and (type(value) ~= "number" or value < 0 or value > 150) then
            error("年龄必须是0-150之间的数字")
        elseif key == "name" and type(value) ~= "string" then
            error("姓名必须是字符串")
        else
            rawset(table, key, value)
        end
    end
}
setmetatable(user, mt)
user.name = "张三"  -- 正常
user.age = 25      -- 正常
-- user.age = -1    -- 错误:年龄必须是 0-150 之间的数字
-- user.name = 123  -- 错误:姓名必须是字符串

# 4. 算术运算元方法

# __add 元方法
local Vector = {}
Vector.__index = Vector
function Vector.new(x, y)
    local v = {x = x, y = y}
    setmetatable(v, Vector)
    return v
end
function Vector.__add(a, b)
    return Vector.new(a.x + b.x, a.y + b.y)
end
function Vector.__tostring(v)
    return "Vector(" .. v.x .. ", " .. v.y .. ")"
end
local v1 = Vector.new(1, 2)
local v2 = Vector.new(3, 4)
local v3 = v1 + v2
print(v3)  -- 输出:Vector (4, 6)
# 其他算术元方法
local Number = {}
Number.__index = Number
function Number.new(value)
    local n = {value = value}
    setmetatable(n, Number)
    return n
end
function Number.__add(a, b)
    return Number.new(a.value + b.value)
end
function Number.__sub(a, b)
    return Number.new(a.value - b.value)
end
function Number.__mul(a, b)
    return Number.new(a.value * b.value)
end
function Number.__div(a, b)
    return Number.new(a.value / b.value)
end
function Number.__tostring(n)
    return tostring(n.value)
end
local n1 = Number.new(10)
local n2 = Number.new(3)
print(n1 + n2)  -- 输出:13
print(n1 - n2)  -- 输出:7
print(n1 * n2)  -- 输出:30
print(n1 / n2)  -- 输出:3.3333333333333

# 5. 比较运算元方法

# __eq 元方法
local Point = {}
Point.__index = Point
function Point.new(x, y)
    local p = {x = x, y = y}
    setmetatable(p, Point)
    return p
end
function Point.__eq(a, b)
    return a.x == b.x and a.y == b.y
end
function Point.__tostring(p)
    return "Point(" .. p.x .. ", " .. p.y .. ")"
end
local p1 = Point.new(1, 2)
local p2 = Point.new(1, 2)
local p3 = Point.new(2, 1)
print(p1 == p2)  -- 输出:true
print(p1 == p3)  -- 输出:false
# __lt 和 __le 元方法
local Student = {}
Student.__index = Student
function Student.new(name, score)
    local s = {name = name, score = score}
    setmetatable(s, Student)
    return s
end
function Student.__lt(a, b)
    return a.score < b.score
end
function Student.__le(a, b)
    return a.score <= b.score
end
function Student.__tostring(s)
    return s.name .. "(" .. s.score .. ")"
end
local s1 = Student.new("张三", 85)
local s2 = Student.new("李四", 92)
local s3 = Student.new("王五", 85)
print(s1 < s2)   -- 输出:true
print(s2 < s1)   -- 输出:false
print(s1 <= s3)  -- 输出:true

# 6. 其他重要元方法

# __tostring 元方法
local Person = {}
Person.__index = Person
function Person.new(name, age)
    local p = {name = name, age = age}
    setmetatable(p, Person)
    return p
end
function Person.__tostring(p)
    return "Person{name='" .. p.name .. "', age=" .. p.age .. "}"
end
local person = Person.new("张三", 25)
print(person)  -- 输出:Person {name=' 张三 ', age=25}
# __call 元方法
local Multiplier = {}
Multiplier.__index = Multiplier
function Multiplier.new(factor)
    local m = {factor = factor}
    setmetatable(m, Multiplier)
    return m
end
function Multiplier.__call(m, value)
    return value * m.factor
end
local double = Multiplier.new(2)
local triple = Multiplier.new(3)
print(double(5))   -- 输出:10
print(triple(5))   -- 输出:15
print(double(10))  -- 输出:20
# __len 元方法
local Set = {}
Set.__index = Set
function Set.new(...)
    local s = {}
    for _, value in ipairs({...}) do
        s[value] = true
    end
    setmetatable(s, Set)
    return s
end
function Set.__len(s)
    local count = 0
    for _ in pairs(s) do
        count = count + 1
    end
    return count
end
local set = Set.new("a", "b", "c", "d")
print(#set)  -- 输出:4

# 7. 元表的实际应用

# 面向对象编程
local Class = {}
Class.__index = Class
function Class.new()
    local obj = {}
    setmetatable(obj, Class)
    return obj
end
function Class:method()
    return "这是类的方法"
end
local obj = Class.new()
print(obj:method())  -- 输出:这是类的方法
# 代理模式
local original = {x = 10, y = 20}
local proxy = {}
local mt = {
    __index = function(table, key)
        print("访问键: " .. key)
        return original[key]
    end,
    __newindex = function(table, key, value)
        print("设置键: " .. key .. " = " .. tostring(value))
        original[key] = value
    end
}
setmetatable(proxy, mt)
print(proxy.x)  -- 输出:访问键: x, 10
proxy.y = 30   -- 输出:设置键: y = 30
print(original.y)  -- 输出:30
# 缓存机制
local cache = {}
local expensive_calculations = {}
local mt = {
    __index = function(table, key)
        if not cache[key] then
            print("计算 " .. key .. " 的值")
            cache[key] = expensive_calculations[key] or "默认值"
        end
        return cache[key]
    end
}
setmetatable(expensive_calculations, mt)
print(expensive_calculations["result1"])  -- 输出:计算 result1 的值,默认值
print(expensive_calculations["result1"])  -- 输出:默认值(从缓存获取)

# 2.15 协程

协程(coroutine)是 Lua 中实现协作式多任务的重要机制。协程允许函数在执行过程中暂停和恢复,从而实现复杂的控制流程。

# 1. 协程的基本概念

# 创建协程
-- 创建协程
local co = coroutine.create(function()
    print("协程开始执行")
    print("协程执行中...")
    print("协程结束")
end)
print(type(co))  -- 输出:thread
print(coroutine.status(co))  -- 输出:suspended
# 启动协程
local co = coroutine.create(function()
    print("协程开始")
    return "协程返回值"
end)
-- 启动协程
local success, result = coroutine.resume(co)
print(success, result)  -- 输出:true 协程返回值
print(coroutine.status(co))  -- 输出:dead

# 2. 协程的状态

# 协程状态检查
local co = coroutine.create(function()
    print("协程运行中")
    coroutine.yield("暂停")
    print("协程恢复")
end)
print("初始状态:", coroutine.status(co))  -- 输出:suspended
coroutine.resume(co)
print("yield后状态:", coroutine.status(co))  -- 输出:suspended
coroutine.resume(co)
print("完成状态:", coroutine.status(co))  -- 输出:dead
# 协程状态说明
-- suspended: 协程已创建但未启动,或已暂停
-- running: 协程正在运行
-- dead: 协程已结束
-- normal: 协程正在调用另一个协程
local co = coroutine.create(function()
    print("状态:", coroutine.status(coroutine.running()))
    coroutine.yield()
end)
print("创建后:", coroutine.status(co))  -- suspended
coroutine.resume(co)  -- 输出:状态: running
print("yield后:", coroutine.status(co))  -- suspended
coroutine.resume(co)
print("完成后:", coroutine.status(co))  -- dead

# 3. 协程的数据传递

# yield 和 resume 传递数据
local co = coroutine.create(function()
    print("协程开始")
    local value = coroutine.yield("第一次yield")
    print("收到值:", value)
    local value2 = coroutine.yield("第二次yield")
    print("收到值:", value2)
    return "协程结束"
end)
local success, result = coroutine.resume(co)
print("第一次resume:", result)  -- 输出:第一次 yield
success, result = coroutine.resume(co, "传递给协程的值1")
print("第二次resume:", result)  -- 输出:第二次 yield
success, result = coroutine.resume(co, "传递给协程的值2")
print("第三次resume:", result)  -- 输出:协程结束
# 双向数据传递
local co = coroutine.create(function()
    local x = coroutine.yield("初始值")
    print("协程收到:", x)
    local y = coroutine.yield("处理后的值")
    print("协程收到:", y)
    return "最终结果"
end)
local success, value = coroutine.resume(co)
print("主程序收到:", value)  -- 输出:初始值
success, value = coroutine.resume(co, "数据1")
print("主程序收到:", value)  -- 输出:处理后的值
success, value = coroutine.resume(co, "数据2")
print("主程序收到:", value)  -- 输出:最终结果

# 4. 协程的实际应用

# 生产者 - 消费者模式
-- 生产者协程
local function producer()
    for i = 1, 5 do
        print("生产:", i)
        coroutine.yield(i)
    end
end
-- 消费者协程
local function consumer()
    local co = coroutine.create(producer)
    while true do
        local success, value = coroutine.resume(co)
        if not success then
            break
        end
        print("消费:", value)
    end
end
consumer()
-- 输出:
-- 生产: 1
-- 消费: 1
-- 生产: 2
-- 消费: 2
-- ...
# 迭代器实现
function iterator(array)
    local i = 0
    return coroutine.create(function()
        while i < #array do
            i = i + 1
            coroutine.yield(array[i])
        end
    end)
end
local numbers = {10, 20, 30, 40, 50}
local iter = iterator(numbers)
while true do
    local success, value = coroutine.resume(iter)
    if not success then
        break
    end
    print(value)
end
# 异步任务模拟
local tasks = {}
function addTask(name, duration)
    table.insert(tasks, {
        name = name,
        duration = duration,
        elapsed = 0
    })
end
function updateTasks(deltaTime)
    for i = #tasks, 1, -1 do
        local task = tasks[i]
        task.elapsed = task.elapsed + deltaTime
        
        if task.elapsed >= task.duration then
            print("任务完成:", task.name)
            table.remove(tasks, i)
        else
            print("任务进行中:", task.name, 
                  string.format("%.1f%%", task.elapsed / task.duration * 100))
        end
    end
end
-- 添加任务
addTask("下载文件", 3)
addTask("处理数据", 2)
addTask("保存结果", 1)
-- 模拟时间流逝
for i = 1, 10 do
    print("时间:", i)
    updateTasks(0.5)
    if #tasks == 0 then
        print("所有任务完成")
        break
    end
end

# 5. 协程的错误处理

# 错误捕获
local co = coroutine.create(function()
    error("协程中的错误")
end)
local success, error_msg = coroutine.resume(co)
if not success then
    print("协程错误:", error_msg)
end
# 安全协程包装器
function safeCoroutine(func)
    return coroutine.create(function(...)
        local success, result = pcall(func, ...)
        if not success then
            print("协程错误:", result)
            return nil
        end
        return result
    end)
end
local co = safeCoroutine(function()
    error("测试错误")
end)
local success, result = coroutine.resume(co)
print("执行结果:", success, result)

# 6. 协程的高级用法

# 协程池
local CoroutinePool = {}
CoroutinePool.__index = CoroutinePool
function CoroutinePool.new(maxSize)
    local pool = {
        maxSize = maxSize or 10,
        available = {},
        inUse = {}
    }
    setmetatable(pool, CoroutinePool)
    return pool
end
function CoroutinePool:acquire(func)
    local co
    if #self.available > 0 then
        co = table.remove(self.available)
    else
        co = coroutine.create(func)
    end
    
    self.inUse[co] = true
    return co
end
function CoroutinePool:release(co)
    if self.inUse[co] then
        self.inUse[co] = nil
        if #self.available < self.maxSize then
            table.insert(self.available, co)
        end
    end
end
-- 使用示例
local pool = CoroutinePool.new(5)
local co1 = pool:acquire(function()
    print("任务1")
    coroutine.yield()
    print("任务1完成")
end)
local co2 = pool:acquire(function()
    print("任务2")
    coroutine.yield()
    print("任务2完成")
end)
coroutine.resume(co1)
coroutine.resume(co2)
pool:release(co1)
pool:release(co2)
# 事件驱动编程
local EventLoop = {}
EventLoop.__index = EventLoop
function EventLoop.new()
    local loop = {
        events = {},
        handlers = {}
    }
    setmetatable(loop, EventLoop)
    return loop
end
function EventLoop:addHandler(event, handler)
    if not self.handlers[event] then
        self.handlers[event] = {}
    end
    table.insert(self.handlers[event], handler)
end
function EventLoop:emit(event, ...)
    if self.handlers[event] then
        for _, handler in ipairs(self.handlers[event]) do
            local co = coroutine.create(handler)
            coroutine.resume(co, ...)
        end
    end
end
-- 使用示例
local loop = EventLoop.new()
loop:addHandler("user_login", function(username)
    print("用户登录:", username)
    coroutine.yield()
    print("处理登录完成")
end)
loop:addHandler("user_logout", function(username)
    print("用户登出:", username)
end)
loop:emit("user_login", "张三")
loop:emit("user_logout", "李四")

# 7. 协程的性能考虑

# 内存使用
-- 协程会占用一定的内存
local function memoryTest()
    local cos = {}
    for i = 1, 1000 do
        cos[i] = coroutine.create(function()
            coroutine.yield()
        end)
    end
    print("创建了1000个协程")
end
memoryTest()
# 协程 vs 线程
-- 协程是协作式的,需要主动让出控制权
local co = coroutine.create(function()
    for i = 1, 1000000 do
        if i % 100000 == 0 then
            coroutine.yield()  -- 定期让出控制权
        end
    end
end)
-- 主程序可以控制协程的执行
while coroutine.status(co) ~= "dead" do
    coroutine.resume(co)
    print("主程序执行其他任务")
end

# 8. 协程的最佳实践

# 避免无限循环
-- 错误:可能导致死锁
local co = coroutine.create(function()
    while true do
        -- 没有 yield,协程永远不会暂停
    end
end)
-- 正确:定期 yield
local co = coroutine.create(function()
    while true do
        -- 执行一些工作
        coroutine.yield()  -- 让出控制权
    end
end)
# 资源管理
local function withResource(resource, func)
    local co = coroutine.create(func)
    local success, result = coroutine.resume(co)
    
    -- 确保资源被释放
    if resource and resource.close then
        resource:close()
    end
    
    return success, result
end
-- 使用示例
local resource = {close = function() print("资源已释放") end}
withResource(resource, function()
    print("使用资源")
    coroutine.yield()
    print("继续使用资源")
end)

# 3. 错误处理和调试

# 3.1 错误处理机制

# pcall 和 xpcall

-- 使用 pcall 进行错误处理
local function riskyFunction(x)
    if x < 0 then
        error("x不能为负数")
    end
    return x * 2
end
local success, result = pcall(riskyFunction, 5)
if success then
    print("结果:", result)  -- 输出:结果: 10
else
    print("错误:", result)  -- 输出错误信息
end
local success, result = pcall(riskyFunction, -1)
if success then
    print("结果:", result)
else
    print("错误:", result)  -- 输出:错误: x 不能为负数
end
-- 使用 xpcall(可以设置错误处理函数)
local function errorHandler(err)
    print("捕获到错误:", err)
    return "错误已处理"
end
local success, result = xpcall(riskyFunction, errorHandler, -1)
print("xpcall结果:", result)  -- 输出:错误已处理

# assert 函数

local function divide(a, b)
    assert(b ~= 0, "除数不能为零")
    return a / b
end
print(divide(10, 2))  -- 输出:5
-- print (divide (10, 0))  -- 错误:除数不能为零

# 3.2 调试技巧

# 使用 print 进行调试

local function debugFunction(x, y)
    print("调试信息: x =", x, "y =", y)
    local result = x + y
    print("计算结果:", result)
    return result
end
debugFunction(5, 3)

# 使用 debug 库

local function debugInfo()
    print("当前行号:", debug.getinfo(1).currentline)
    print("函数名:", debug.getinfo(1).name)
    print("源文件:", debug.getinfo(1).source)
end
debugInfo()

# 4. 模块系统

# 4.1 创建模块

-- math_utils.lua
local math_utils = {}
function math_utils.add(a, b)
    return a + b
end
function math_utils.subtract(a, b)
    return a - b
end
function math_utils.multiply(a, b)
    return a * b
end
function math_utils.divide(a, b)
    assert(b ~= 0, "除数不能为零")
    return a / b
end
-- 返回模块
return math_utils

# 4.2 使用模块

-- 加载模块
local math_utils = require("math_utils")
-- 使用模块函数
print(math_utils.add(5, 3))      -- 输出:8
print(math_utils.multiply(4, 6)) -- 输出:24

# 4.3 模块的局部性

-- 私有函数(不导出)
local function privateFunction()
    return "这是私有函数"
end
-- 公共函数(导出)
local function publicFunction()
    return privateFunction() .. " 通过公共函数访问"
end
return {
    publicFunction = publicFunction
}

# 5. 文件操作

# 5.1 基本文件操作

-- 写入文件
local file = io.open("test.txt", "w")
if file then
    file:write("Hello Lua\n")
    file:write("这是第二行\n")
    file:close()
    print("文件写入成功")
else
    print("无法打开文件")
end
-- 读取文件
local file = io.open("test.txt", "r")
if file then
    local content = file:read("*all")
    print("文件内容:")
    print(content)
    file:close()
else
    print("无法打开文件")
end

# 5.2 逐行读取

local file = io.open("test.txt", "r")
if file then
    for line in file:lines() do
        print("行:", line)
    end
    file:close()
end

# 5.3 文件模式

-- "r": 只读模式
-- "w": 写入模式(覆盖)
-- "a": 追加模式
-- "r+": 读写模式
-- "w+": 读写模式(覆盖)
local file = io.open("append.txt", "a")
if file then
    file:write("追加的内容\n")
    file:close()
end

# 6. 标准库

# 6.1 数学库

-- 基本数学函数
print(math.abs(-5))      -- 绝对值:5
print(math.floor(3.7))   -- 向下取整:3
print(math.ceil(3.2))    -- 向上取整:4
print(math.max(1, 5, 3)) -- 最大值:5
print(math.min(1, 5, 3)) -- 最小值:1
print(math.random())      -- 随机数
print(math.pi)           -- 圆周率

# 6.2 字符串库

local str = "  Hello World  "
-- 去除空白
print(string.gsub(str, "^%s*(.-)%s*$", "%1"))
-- 字符串格式化
print(string.format("姓名:%s,年龄:%d", "张三", 25))
-- 字符串匹配
local email = "user@example.com"
local username = string.match(email, "([^@]+)")
print("用户名:", username)

# 6.3 表库

local arr = {3, 1, 4, 1, 5, 9}
-- 排序
table.sort(arr)
print(table.concat(arr, ", "))
-- 插入和删除
table.insert(arr, 2, "插入")
print(table.concat(arr, ", "))
local removed = table.remove(arr, 1)
print("删除的元素:", removed)

# 6.4 操作系统库

-- 获取当前时间
print(os.time())
-- 格式化时间
local time = os.time()
print(os.date("%Y-%m-%d %H:%M:%S", time))
-- 执行系统命令
local result = os.execute("ls")
print("命令执行结果:", result)

# 7. 性能优化

# 7.1 局部变量

-- 低效:使用全局变量
for i = 1, 1000000 do
    print = print  -- 全局查找
end
-- 高效:使用局部变量
local print = print
for i = 1, 1000000 do
    print = print  -- 局部查找
end

# 7.2 表预分配

-- 低效:频繁重新分配
local arr = {}
for i = 1, 10000 do
    table.insert(arr, i)
end
-- 高效:预分配空间
local arr = {}
for i = 1, 10000 do
    arr[i] = i
end

# 7.3 字符串连接优化

-- 低效:频繁连接
local result = ""
for i = 1, 1000 do
    result = result .. i
end
-- 高效:使用 table.concat
local parts = {}
for i = 1, 1000 do
    table.insert(parts, tostring(i))
end
local result = table.concat(parts)

# 8. 最佳实践

# 8.1 代码风格

-- 使用有意义的变量名
local userName = "张三"
local userAge = 25
-- 使用局部变量
local function calculateArea(width, height)
    return width * height
end
-- 添加注释
-- 计算两个数的最大公约数
local function gcd(a, b)
    while b ~= 0 do
        a, b = b, a % b
    end
    return a
end

# 8.2 错误处理

local function safeDivide(a, b)
    if b == 0 then
        return nil, "除数不能为零"
    end
    return a / b, nil
end
local result, error = safeDivide(10, 2)
if error then
    print("错误:", error)
else
    print("结果:", result)
end

# 8.3 资源管理

local function withFile(filename, callback)
    local file = io.open(filename, "r")
    if not file then
        return nil, "无法打开文件"
    end
    
    local success, result = pcall(callback, file)
    file:close()
    
    if not success then
        return nil, result
    end
    return result
end
local content, error = withFile("test.txt", function(file)
    return file:read("*all")
end)

# 9. 常见陷阱和注意事项

# 9.1 数组索引从 1 开始

local arr = {"a", "b", "c"}
print(arr[0])  -- 输出:nil
print(arr[1])  -- 输出:a

# 9.2 表的引用特性

local t1 = {1, 2, 3}
local t2 = t1  -- t2 是 t1 的引用
t2[1] = 10
print(t1[1])   -- 输出:10

# 9.3 字符串不可变性

local str = "hello"
local str2 = str:upper()  -- 创建新字符串
print(str)   -- 输出:hello
print(str2)  -- 输出:HELLO

# 9.4 闭包陷阱

-- 错误的闭包使用
local functions = {}
for i = 1, 3 do
    functions[i] = function()
        print(i)  -- 所有函数都会打印 3
    end
end
-- 正确的闭包使用
local functions = {}
for i = 1, 3 do
    functions[i] = (function(value)
        return function()
            print(value)
        end
    end)(i)
end

# 10. 总结

Lua 是一个强大而灵活的脚本语言,具有以下特点:

  1. 简洁性:语法简洁,易于学习和使用
  2. 灵活性:动态类型,支持多种编程范式
  3. 可嵌入性:可以轻松嵌入到其他应用程序中
  4. 高性能:执行效率高,内存占用小
  5. 跨平台:支持多种操作系统和硬件平台

通过掌握 Lua 的基本语法、数据结构、函数、表、元表、协程等核心概念,你可以:

  • 编写高效的脚本程序
  • 实现复杂的算法和数据结构
  • 进行面向对象编程
  • 处理文件和网络操作
  • 进行错误处理和调试

Lua 特别适合用于:

  • 游戏脚本
  • 配置文件处理
  • 嵌入式系统
  • 网络应用
  • 自动化脚本

希望这篇 Lua 入门指南能够帮助你快速掌握 Lua 编程,并在实际项目中发挥其强大的功能。

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

ZJM 微信支付

微信支付

ZJM 支付宝

支付宝