所谓“迭代器”就是一种可以遍历一种集合中所有元素的机制。在Lua中,通常将迭代器表示为函数。每调用一次函数,即返回集合中的“下一个”元素。
function values(t) local i = 0 return function() i = i + 1 return t[i] end end
在上例中,values就是一个工厂。每当调用这个工厂时,它就创建一个新的closure(即迭代器本身)。这closure 将它的状态保存在其外部变量t 和i 中。每当调用这个迭代器时,它就从列表t 中返回下一个值。直到最后一个元素返回后,迭代器就会返回nil,以此表示迭代的结束。
泛型for语法:
for <var-list> in <exp-list> do <body> end
其中,<var-list>是一个或多个变量名的列表,以逗号分隔;<exp-list>是一个或多个表达式的列表,同样以逗号分隔。通常表达式只有一个元素,即一句对迭代器工厂的调用。for 做的第一件事是对in 后面的表达式求值。
简单示例:
function values(t) local i = 0 return function() i = i + 1 return t[i] end end t = {1, 2, 3} for element in values(t) do print(element) end
“无状态的迭代器”就是一种自身不保存任何状态的迭代器。因此,我们可以在多个循环中使用同一个无状态的迭代器,避免创建新的closure 开销。
在每次迭代中,for循环都会用恒定状态和控制变量来调用迭代器函数。一个无状态的迭代器可以根据这两个值来为下次迭代生成下一个元素。这类迭代器的一个典型例子就是ipairs,它可以用来迭代一个数组的所有元素:
a = {"one", "two", "three"} for i, v in ipairs(a) do print(i, v) end
函数pairs 与ipairs 类似,也是用于遍历一个table中的所有元素。不同的是,它的迭代函数是Lua中的一个基本函数next。
function pairs(t) return next, t, nil end
关于无状态迭代器的另一个有趣例子是一种可以遍历链表的迭代器:
local function getnext(list, node) if not node then return list else return node.next end end function traverse(list) return getnext, list, nil end
list = nil for line in io.lines() do list = {val = line, next = list} end for node in traverse(list) do print(node.val) end
文件操作:
--读取文件,显示文件内容 local f = assert(io.open("test2.lua", 'r')) --相当于获取流的指针或句柄或对象 --'r'读取(read),'a'追加(append),'w'写入(write),'b'以二进制形式打开(binary) local string = f:read("*all") --*all读取所有,*line读取一行,*number读取一个数字,<num>读取一个不超过<num>个数的字符 f:close() --关闭流 print(string)
--写入文件 local f = assert(io.open("test2.txt", 'w')) f:write("welcome to lua \n I'm Jacedy") f:close()