# 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
无效标识符示例:
# 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
注意: 这些关键字区分大小写,例如 And 或 AND 不是关键字,可以作为标识符使用。
# 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 aprint ( a) print ( type ( a) ) b = 10 b = nil print ( b)
# 2. boolean(布尔值)
只有两个值:true 和 false。在 Lua 中,只有 nil 和 false 为假,其他所有值都为真(包括 0 和空字符串)。
local flag1 = true local flag2 = false print ( type ( flag1) ) 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) ) print ( int_num + float_num)
# 4. string(字符串)
字符串是不可变的值,可以用单引号、双引号或长括号定义。
local str1 = 'Hello' local str2 = "World" local str3 = [[ 多行字符串 可以包含换行 ]] local result = str1 .. " " .. str2 print ( # str1)
# 5. function(函数)
函数是第一类值,可以赋值给变量,作为参数传递。
function greet ( name) return "Hello, " .. name end local sayHello = greetprint ( sayHello ( "Lua" ) ) print ( type ( greet) )
# 6. table(表)
Lua 中唯一的数据结构,可以实现数组、字典、对象等。
local arr = { 1 , 2 , 3 , 4 , 5 } print ( arr[ 1 ] ) local dict = { name = "张三" , age = 25 , city = "北京" } print ( dict. name) print ( dict[ "age" ] ) print ( type ( arr) )
# 7. userdata(用户数据)
用于存储 C 数据的类型,通常用于 Lua 与 C 程序的交互。
# 8. thread(线程)
表示协程,用于实现协作式多任务。
local co = coroutine. create ( function ( ) print ( "协程执行" ) end ) print ( type ( co) )
# 类型检查函数
使用 type() 函数可以获取变量的类型:
print ( type ( nil ) ) print ( type ( true ) ) print ( type ( 42 ) ) print ( type ( "hello" ) ) print ( type ( { } ) ) print ( type ( print) )
# 2.6 循环
Lua 提供了多种循环结构来重复执行代码块。
# 1. while 循环
当条件为真时重复执行代码块。
语法:
示例:
local i = 1 while i <= 5 do print ( "第" .. i .. "次循环" ) i = i + 1 end
# 2. for 循环
Lua 有两种 for 循环:数值 for 循环和泛型 for 循环。
# 数值 for 循环
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 循环
先执行循环体,然后检查条件。至少执行一次。
语法:
示例:
local i = 1 repeat print ( "repeat循环:" .. i) i = i + 1 until i > 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 end print ( i) end
# goto 语句(Lua 5.2+)
跳转到指定标签。可以用来模拟 continue 的效果。
for i = 1 , 5 do if i == 3 then goto continue end print ( i) :: continue:: end
注意: Lua 没有 continue 语句,但可以使用 goto 或者重构代码逻辑来实现类似效果。
# 6. 无限循环
while true do local input = io. read ( ) if input == "quit" then break end print ( "你输入了:" .. input) end repeat local shouldContinue = someCondition ( ) until not shouldContinue
# 2.7 控制结构语句
Lua 提供了条件控制语句来根据不同条件执行不同的代码块。
# 1. if 语句
最基本的条件语句,当条件为真时执行代码块。
语法:
示例:
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 elseif condition2 then elseif condition3 then 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 中,只有 nil 和 false 被认为是假值,其他所有值都是真值。
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 if age >= 18 and income >= 3000 then print ( "符合贷款条件" ) end if age < 18 or age > 65 then print ( "特殊年龄段" ) end 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 来模拟:
local age = 20 local status = age >= 18 and "成年人" or "未成年人" print ( status) local result = true and false or "default" 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" ) )
# 匿名函数(函数表达式)
local add = function ( a, b) return a + b end print ( add ( 3 , 5 ) ) local result = ( function ( x) return x * x end ) ( 5 ) print ( result)
# 2. 函数参数
# 固定参数
function multiply ( a, b) return a * b end print ( multiply ( 4 , 5 ) )
# 可变参数
使用 ... 表示可变参数。
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 ) ) 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 ( ) ) print ( greet ( "Lua" ) ) print ( greet ( "Lua" , "Hi" ) )
# 3. 函数返回值
# 单个返回值
function square ( x) return x * x end local result = square ( 4 ) print ( result)
# 多个返回值
function divmod ( a, b) return math. floor ( a / b) , a % b end local quotient, remainder = divmod ( 17 , 5 ) print ( quotient, remainder) local q = divmod ( 17 , 5 ) print ( q)
# 返回表
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 factorialfactorial = function ( n) if n <= 1 then return 1 else return n * factorial ( n - 1 ) end end print ( factorial ( 5 ) )
# 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) ) print ( applyOperation ( 3 , 4 , multiply) ) print ( applyOperation ( 3 , 4 , function ( x, y) return x - y end ) )
# 6. 闭包
函数可以访问其外部作用域的变量。
function createCounter ( ) local count = 0 return function ( ) count = count + 1 return count end end local counter1 = createCounter ( ) local counter2 = createCounter ( ) print ( counter1 ( ) ) print ( counter1 ( ) ) print ( counter2 ( ) ) print ( counter1 ( ) )
# 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 ) ) print ( math_utils. subtract ( 5 , 3 ) ) local person = { name = "张三" , greet = function ( self) return "Hello, I'm " .. self. name end } print ( person. greet ( person) ) 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 ) )
# 9. 函数的一些内置函数
function testFunc ( ) end print ( type ( testFunc) ) 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) 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) print ( a - b) print ( a * b) print ( a / b) print ( a // b) print ( a % b) print ( a ^ b) print ( - a) local result = ( a + b) * 2 - a / bprint ( result)
# 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) print ( x ~= y) print ( x < y) print ( x > y) print ( x <= y) print ( x >= y) local str1 = "apple" local str2 = "banana" print ( str1 < str2) print ( 10 == "10" ) print ( nil == 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) print ( a or b) print ( not a) print ( not b) print ( false and print ( "不会执行" ) ) print ( true or 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)
# 4. 其他运算符
# 字符串连接运算符 (..)
local firstName = "张" local lastName = "三" local fullName = firstName .. lastNameprint ( fullName) local age = 25 local message = "我今年" .. age .. "岁" print ( message) local result = "a" .. "b" .. "c" .. "d" print ( result)
# 长度运算符 (#)
local str = "Hello" print ( # str) local arr = { 1 , 2 , 3 , 4 , 5 } print ( # arr) local sparse = { 1 , 2 , nil , 4 , 5 } print ( # sparse) local chinese = "你好" print ( # chinese)
# 5. 运算符优先级
从高到低的优先级顺序:
^ (幂运算)
not # - (一元运算符)
* / // %
+ -
.. (字符串连接)
< > <= >= ~= ==
and
or
local result1 = 2 + 3 * 4 local result2 = 2 ^ 3 * 4 local result3 = not false or true and false print ( result1) print ( result2) print ( result3) local result4 = ( 2 + 3 ) * 4 print ( result4)
# 6. 类型转换
Lua 在某些运算中会自动进行类型转换。
print ( "10" + 5 ) print ( "3.14" * 2 ) print ( 10 .. 20 ) local str = "123" local num = tonumber ( str) print ( num + 10 ) local number = 456 local string = tostring ( number) print ( string .. "789" )
# 7. 比较运算的特殊情况
local t1 = { 1 , 2 , 3 } local t2 = { 1 , 2 , 3 } local t3 = t1print ( t1 == t2) print ( t1 == t3) local function f1 ( ) end local function f2 ( ) end local f3 = f1print ( f1 == f2) print ( f1 == f3) local nan = 0 / 0 print ( nan == 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) print ( str2) print ( str3) print ( str4)
# 长字符串(多行字符串)
使用 [[]] 定义多行字符串,可以包含换行符。
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" print ( str2)
# 3. 字符串连接
使用 .. 运算符连接字符串。
local first = "Hello" local second = "World" local result = first .. " " .. secondprint ( result) local age = 25 local message = "我今年" .. age .. "岁" print ( message) local path = "home" .. "/" .. "user" .. "/" .. "documents" print ( path)
# 4. 字符串长度
使用 # 运算符获取字符串长度(字节数)。
local str = "Hello" print ( # str) local chinese = "你好" print ( # chinese) local empty = "" print ( # empty)
# 5. 字符串库函数
Lua 提供了丰富的字符串处理函数。
# 大小写转换
local str = "Hello World" print ( string. upper ( str) ) print ( string. lower ( str) ) print ( str: upper ( ) ) print ( str: lower ( ) )
# 字符串查找
local text = "Hello Lua World" local start, finish = string. find ( text, "Lua" ) print ( start, finish) local start, finish = text: find ( "World" ) print ( start, finish) local pos = text: find ( "Python" ) print ( pos)
# 字符串替换
local text = "Hello World, Hello Lua" local result1 = string. gsub ( text, "Hello" , "Hi" , 1 ) print ( result1) local result2 = string. gsub ( text, "Hello" , "Hi" ) print ( result2) local result3 = text: gsub ( "Hello" , "Greetings" ) print ( result3)
# 字符串截取
local text = "Hello World" local sub1 = string. sub ( text, 1 , 5 ) print ( sub1) local sub2 = string. sub ( text, 7 ) print ( sub2) local sub3 = string. sub ( text, - 5 ) print ( sub3) local sub4 = text: sub ( 1 , 5 ) print ( sub4)
# 字符串分割
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
# 字符串格式化
local name = "张三" local age = 25 local score = 85.5 local message = string. format ( "姓名:%s,年龄:%d,分数:%.1f" , name, age, score) print ( message) print ( string. format ( "%d" , 42 ) ) print ( string. format ( "%.2f" , 3.14159 ) ) print ( string. format ( "%s" , "hello" ) ) print ( string. format ( "%x" , 255 ) ) print ( string. format ( "%o" , 8 ) )
# 字符串匹配和模式
local text = "The price is $123.45" local number = text: match ( "%d+" ) print ( number) local price = text: match ( "%d+%.%d+" ) print ( price) for num in text: gmatch ( "%d+" ) do print ( num) end local email = "user@example.com" local username = email: match ( "([^@]+)" ) print ( username)
# 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 for num in text: gmatch ( "%d+" ) do print ( num) end for item in text: gmatch ( "%w+" ) do print ( item) end
# 7. 字符串和数字的转换
local str_num = "123" local num = tonumber ( str_num) print ( num + 10 ) local invalid = "abc" local result = tonumber ( invalid) print ( result) local number = 456 local str = tostring ( number) print ( str .. "789" ) print ( "10" + 5 ) print ( 10 .. 20 )
# 8. 实用字符串处理示例
function trim ( str) return str: match ( "^%s*(.-)%s*$" ) end local text = " Hello World " print ( "'" .. trim ( text) .. "'" ) function isEmpty ( str) return str == nil or str == "" or str: match ( "^%s*$" ) ~= nil end print ( isEmpty ( "" ) ) print ( isEmpty ( " " ) ) print ( isEmpty ( "hello" ) ) function capitalize ( str) return str: sub ( 1 , 1 ) : upper ( ) .. str: sub ( 2 ) : lower ( ) end print ( capitalize ( "hello" ) ) print ( capitalize ( "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 ] ) print ( mixed[ 2 ] )
# 动态创建
local arr = { } arr[ 1 ] = "第一个元素" arr[ 2 ] = "第二个元素" arr[ 3 ] = "第三个元素" local list = { } table. insert ( list, "元素1" ) table. insert ( list, "元素2" ) table. insert ( list, "元素3" ) print ( list[ 1 ] )
# 2. 数组长度
使用 # 运算符获取数组长度。
local arr = { 10 , 20 , 30 , 40 , 50 } print ( # arr) local empty = { } print ( # empty) local sparse = { 1 , 2 , nil , 4 , 5 } print ( # sparse)
# 3. 数组遍历
# 使用数值 for 循环
local fruits = { "苹果" , "香蕉" , "橙子" , "葡萄" } for i = 1 , # fruits do print ( i, fruits[ i] ) end
# 使用 ipairs 迭代器
local numbers = { 10 , 20 , 30 , 40 , 50 } for index, value in ipairs ( numbers) do print ( index, value) end
# ipairs vs pairs
local arr = { 10 , 20 , nil , 40 , 50 } print ( "使用ipairs:" ) for i, v in ipairs ( arr) do print ( i, v) end print ( "使用pairs:" ) for i, v in pairs ( arr) do print ( i, v) end
# 4. 数组操作
# 添加元素
local arr = { 1 , 2 , 3 } table. insert ( arr, 4 ) print ( table. concat ( arr, ", " ) ) table. insert ( arr, 2 , "插入的元素" ) print ( table. concat ( arr, ", " ) ) arr[ # arr + 1 ] = 5 print ( table. concat ( arr, ", " ) )
# 删除元素
local arr = { "a" , "b" , "c" , "d" , "e" } local removed = table. remove ( arr) print ( "删除的元素:" , removed) print ( table. concat ( arr, ", " ) ) local removed2 = table. remove ( arr, 2 ) print ( "删除的元素:" , removed2) print ( table. concat ( arr, ", " ) ) 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, ", " ) ) local numbers2 = { 5 , 2 , 8 , 1 , 9 , 3 } table. sort ( numbers2, function ( a, b) return a > b end ) print ( table. concat ( numbers2, ", " ) ) 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 ] ) for i = 1 , # matrix do for j = 1 , # matrix[ i] do io. write ( matrix[ i] [ j] .. " " ) end print ( ) end 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) 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, ", " ) ) 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, ", " ) ) 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, ", " ) ) 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, ", " ) )
# 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)
# 9. 数组的注意事项
local arr = { "a" , "b" , "c" } print ( arr[ 0 ] ) print ( arr[ 1 ] ) local sparse = { } sparse[ 1 ] = "first" sparse[ 5 ] = "fifth" sparse[ 10 ] = "tenth" print ( "长度:" , # sparse) local mixed = { "first" , "second" , name = "张三" , age = 25 } print ( "数组长度:" , # mixed) print ( "姓名:" , mixed. name) 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 local arr = { 1 , 2 , nil , 4 , 5 } for i, v in ipairs ( arr) do print ( i, v) end
# 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 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
# 有状态迭代器
使用闭包保存迭代状态。
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
# 目录遍历迭代器
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" , "second" , name = "张三" , age = 25 }
# 访问表元素
local person = { name = "张三" , age = 25 , city = "北京" } print ( person. name) print ( person[ "age" ] ) print ( person[ 1 ] ) 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 = "程序员" } for key, value in pairs ( person) do print ( key .. " = " .. tostring ( value) ) end 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 } for index, value in ipairs ( arr) do print ( index .. ": " .. value) end 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) print ( table. concat ( numbers, ", " ) ) local removed2 = table. remove ( numbers, 2 ) print ( "删除的元素:" , removed2) print ( table. concat ( numbers, ", " ) )
# table.concat
local words = { "Hello" , "World" , "from" , "Lua" } local sentence = table. concat ( words, " " ) print ( sentence) local partial = table. concat ( words, " | " , 2 , 3 ) print ( partial)
# table.sort
local numbers = { 5 , 2 , 8 , 1 , 9 , 3 } table. sort ( numbers) print ( table. concat ( numbers, ", " ) ) table. sort ( numbers, function ( a, b) return a > b end ) print ( table. concat ( numbers, ", " ) ) 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 local copy2 = { } table. move ( original, 1 , # original, 1 , copy2) print ( copy[ 1 ] , copy[ 4 ] [ 1 ] ) copy[ 4 ] [ 1 ] = 10 print ( original[ 4 ] [ 1 ] )
# 深拷贝
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 ] )
# 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" ) ) print ( isInSet ( set, "orange" ) )
# 实现队列
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) ) print ( peek ( queue) )
# 实现栈
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) ) print ( top ( stack) )
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)
# 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) if getmetatable ( t) then print ( "表有元表" ) end
# 元表的保护
local t = { } local mt = { } setmetatable ( t, mt) mt. __metatable = "受保护的元表" local success = pcall ( function ( ) setmetatable ( t, { } ) end ) print ( success)
# 2. __index 元方法
# 处理不存在的键
local t = { a = 1 , b = 2 } local mt = { __index = function ( table, key) return "键 '" .. key .. "' 不存在" end } setmetatable ( t, mt) print ( t. a) print ( t. c) print ( t[ "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) ) print ( child. nonexistent)
# 默认值表
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) print ( config1. height) print ( config2. width)
# 3. __newindex 元方法
# 控制赋值行为
local t = { } local mt = { __newindex = function ( table, key, value) print ( "尝试设置 " .. key .. " = " .. tostring ( value) ) end } setmetatable ( t, mt) t. x = 10 print ( t. x)
# 只读表
local readOnly = { a = 1 , b = 2 } local mt = { __newindex = function ( table, key, value) error ( "表是只读的,不能修改键: " .. key) end } setmetatable ( readOnly, mt) print ( readOnly. a)
# 数据验证
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
# 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 + v2print ( v3)
# 其他算术元方法
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) print ( n1 - n2) print ( n1 * n2) print ( n1 / n2)
# 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) print ( p1 == p3)
# __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) print ( s2 < s1) print ( s1 <= s3)
# 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)
# __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 ) ) print ( triple ( 5 ) ) print ( double ( 10 ) )
# __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)
# 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) proxy. y = 30 print ( original. y)
# 缓存机制
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" ] ) print ( expensive_calculations[ "result1" ] )
# 2.15 协程
协程(coroutine)是 Lua 中实现协作式多任务的重要机制。协程允许函数在执行过程中暂停和恢复,从而实现复杂的控制流程。
# 1. 协程的基本概念
# 创建协程
local co = coroutine. create ( function ( ) print ( "协程开始执行" ) print ( "协程执行中..." ) print ( "协程结束" ) end ) print ( type ( co) ) print ( coroutine. status ( co) )
# 启动协程
local co = coroutine. create ( function ( ) print ( "协程开始" ) return "协程返回值" end ) local success, result = coroutine. resume ( co) print ( success, result) print ( coroutine. status ( co) )
# 2. 协程的状态
# 协程状态检查
local co = coroutine. create ( function ( ) print ( "协程运行中" ) coroutine. yield ( "暂停" ) print ( "协程恢复" ) end ) print ( "初始状态:" , coroutine. status ( co) ) coroutine. resume ( co) print ( "yield后状态:" , coroutine. status ( co) ) coroutine. resume ( co) print ( "完成状态:" , coroutine. status ( co) )
# 协程状态说明
local co = coroutine. create ( function ( ) print ( "状态:" , coroutine. status ( coroutine. running ( ) ) ) coroutine. yield ( ) end ) print ( "创建后:" , coroutine. status ( co) ) coroutine. resume ( co) print ( "yield后:" , coroutine. status ( co) ) coroutine. resume ( co) print ( "完成后:" , coroutine. status ( co) )
# 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) success, result = coroutine. resume ( co, "传递给协程的值1" ) print ( "第二次resume:" , result) 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 ( )
# 迭代器实现
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 end end ) 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
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) else print ( "错误:" , result) end local success, result = pcall ( riskyFunction, - 1 ) if success then print ( "结果:" , result) else print ( "错误:" , result) end 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 ) )
# 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 创建模块
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 ) ) print ( math_utils. multiply ( 4 , 6 ) )
# 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 文件模式
local file = io. open ( "append.txt" , "a" ) if file then file: write ( "追加的内容\n" ) file: close ( ) end
# 6. 标准库
# 6.1 数学库
print ( math. abs ( - 5 ) ) print ( math. floor ( 3.7 ) ) print ( math. ceil ( 3.2 ) ) print ( math. max ( 1 , 5 , 3 ) ) print ( math. min ( 1 , 5 , 3 ) ) 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 = printfor 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 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 ] ) print ( arr[ 1 ] )
# 9.2 表的引用特性
local t1 = { 1 , 2 , 3 } local t2 = t1 t2[ 1 ] = 10 print ( t1[ 1 ] )
# 9.3 字符串不可变性
local str = "hello" local str2 = str: upper ( ) print ( str) print ( str2)
# 9.4 闭包陷阱
local functions = { } for i = 1 , 3 do functions[ i] = function ( ) print ( i) end end local functions = { } for i = 1 , 3 do functions[ i] = ( function ( value) return function ( ) print ( value) end end ) ( i) end
# 10. 总结
Lua 是一个强大而灵活的脚本语言,具有以下特点:
简洁性 :语法简洁,易于学习和使用
灵活性 :动态类型,支持多种编程范式
可嵌入性 :可以轻松嵌入到其他应用程序中
高性能 :执行效率高,内存占用小
跨平台 :支持多种操作系统和硬件平台
通过掌握 Lua 的基本语法、数据结构、函数、表、元表、协程等核心概念,你可以:
编写高效的脚本程序
实现复杂的算法和数据结构
进行面向对象编程
处理文件和网络操作
进行错误处理和调试
Lua 特别适合用于:
游戏脚本
配置文件处理
嵌入式系统
网络应用
自动化脚本
希望这篇 Lua 入门指南能够帮助你快速掌握 Lua 编程,并在实际项目中发挥其强大的功能。