上一篇: Lua基础学习(二) https://blog.csdn.net/sun_zeliang/article/details/86644551
Lua迭代器
泛型 for 迭代器
泛型 for 在自己内部保存迭代函数,实际上它保存三个值:迭代函数、状态常量、控制变量。
泛型 for 迭代器提供了集合的 key/value 对,语法格式如下:
for k,v in pairs(t) do
print(k,v)
end
在学习 for循环的时候有学习到泛型 for。
无状态迭代器
无状态的迭代器是指不保留任何状态的迭代器,通常用两个变量(状态常量和控制变量)获取下一个元素,典型的例子就是ipairs。使用起来也非常简单,如下:
array={1,2,3,4,5,6,7}
for k,v in ipairs(array) do
print(k,v)
end
输出如下:
实现一个ipairs也非常简单:
array={1,2,3,4,5,6,7}
function iter(a,i)
i=i+1
local v = a[i]
if v then
return i,v
end
end
function ipairs(a)
return iter,a,0
end
for k,v in ipairs(array) do
print(k,v)
end
调用的迭代器会一直到第一nil出现停止,也就是说如果一个数组内中间有nil,后面的就会被忽略,只能用下标来访问
复杂状态迭代器
很多情况下,迭代器需要保存多个状态信息而不是简单的状态常量和控制变量,最简单的方法是使用闭包,还有一种方法就是将所有的状态信息封装到table内,将table作为迭代器的状态常量,因为这种情况下可以将所有的信息存放在table内,所以迭代函数通常不需要第二个参数。
array={1,2,3,4,5,6,7}
function elementIterator(collection)
local index = 0
local count = #collection
--闭包函数
return function()
index = index + 1
if index <= count
then
--返回迭代器的当前元素
return collection[index]
end
end
end
for element in elementIterator(array) do
print(element)
end
输出:
尽可能的编写无状态的迭代器,如果写不了无状态的迭代器,就用基于闭包函数的迭代器。
Lua table(表)
table的构造
--table 初始化
mytable={}
--指定值
mytable[1]="mytable"
mytable["wow"]="Lua"
--移除引用
mytable=nil
当我们为 table a 并设置元素,然后将 a 赋值给 b,则 a 与 b 都指向同一个内存。如果 a 设置为 nil ,则 b 同样能访问 table 的元素。如果没有指定的变量指向a,Lua的垃圾回收机制会清理相对应的内存。
示例:
a={}
a[1]="Lua"
print("数组a索引为1:",a[1])
b=a
b[1]="C#"
print("数组b索引为1:",b[1])
b=nil
print("b为nil后,数组a索引为1:",a[1])
print("b为nil后,数组b:",b)
a=nil
print("a为nil后,数组a:",a)
输出:
b为nil后,数组b已经是nil了,但是因为数组a的引用还没有被释放,所以数组a索引为1的时候还是有值的,但是当a为nil后,a理所应当的被Lua的垃圾回收清理掉了
table的操作
table库的一些对table的操作
table.concat
连接数组元素,可以指定连接的时候分割字符,可以指定连接的索引
示例:
colors={"red","black","orange","yellow","white"}
--连接数组每个元素
print(table.concat(colors))
--连接每个元素,用,隔开
print(table.concat(colors,","))
--连接索引2-5的元素,用,隔开
print(table.concat(colors,",",2,5))
table.insert
在数组插入元素,有3个参数,中间参数可以不写,默认是最后一个元素
示例:
colors={"red","black","orange","yellow"}
--没有索引,默认在最后插入
table.insert(colors,"white")
print(table.concat(colors,','))
--有索引,在索引处插入
table.insert(colors,3,"purple")
print(table.concat(colors,','))
输出:
table.remove
删除数组中元素,有两个参数,第二个参数可以不写,默认删除最后一个,删除中间的时候,后面的元素会前移
示例:
colors={"red","black","orange","yellow"}
--默认删除最后一个元素
table.remove(colors)
print(table.concat(colors,','))
--删除索引为2的元素
table.remove(colors,2)
print(table.concat(colors,','))
输出:
table.sort
对数组排序 ,也有两个参数,第二个参数是一个比较函数,用来执行排序方式
示例:
colors={"red","black","orange","yellow"}
--默认升序排序
table.sort(colors)
print(table.concat(colors,','))
function compare(a,b)
return a > b
end
--加上比较函数过后,降序排序
table.sort(colors,compare)
print(table.concat(colors,','))
输出:
Lua模块与包
模块类似于一个封装库,从 Lua 5.1 开始,Lua 加入了标准的模块管理机制,可以把一些公用的代码放在一个文件里,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。
定义一个简单的模块
--保存为module.lua文件
module={}
module.constant="这是一个常量"
function module.func1()
io.write("这是一个公有函数!\n")
end
local function func2()
print("这是一个私有函数!")
end
function module.func3()
func2()
end
return module
由上可知,模块的结构就是一个 table 的结构,因此可以像操作调用 table 里的元素那样来操作调用模块里的常量或函数。
require函数
require("module")
print(module.constant)
module.func3()
输出:
也可以给加载的模块或者模块函数给一个别名,比如 local m= require "module"
加载机制
对于自定义的模块,模块文件不是放在哪个文件目录都行,函数 require 有它自己的文件路径加载策略,它会尝试从 Lua 文件或 C 程序库中加载模块。
在搜索一个文件时,require采用的是一连串的模式,其中每一项都是讲模块名转换为路径名,比如路径为:
?;?.lua;C:\windows\?;/user/local/lua/?/?.lua
调用 require "sql" 就会试着打开以下文件
sql
sql.lua
C:\windows\sql
/user/local/lua/sql/sql.lua
Lua支持层级性的模块名,用一个 . 来分隔名称中的层级。
比如上面的同样一个路径:?;?.lua;C:\windows\?;/user/local/lua/?/?.lua
如果调用 require "mod.sql" 打开的文件是:
mod/sql
mod/sql.lua
C:\windows\mod\sql
/user/local/lua/mod/sql/sql.lua
C包
loadlib可以加载和连接指定的库,这个时候并没有打开库,打开库的操作是在调用了返回的函数才打开的。然后返回初始化函数作为Lua的一个函数,这样我们就可以直接在Lua中调用他。
比如:
local path = "/usr/local/lua/lib/libluasocket.so"
-- 或者 path = "C:\\windows\\luasocket.dll",这是 Window 平台下
local f = assert(loadlib(path, "luaopen_socket"))
f() -- 真正打开库
下一篇: Lua基础学习(四) https://blog.csdn.net/sun_zeliang/article/details/86698691