前言
阅读本文之前如果不理解闭包的原理和应用可移步优雅编程-lua实现函数柯里化,本文会带你理解lua中的迭代器原理以及实现
迭代器定义
让我们看一下维基上对迭代器的解释
迭代器(iterator),是确使用户可在容器对象(container,例如链表或数组)上遍访的对象,设计人员使用此接口无需关心容器对象的内存分配的实现细节。其行为很像数据库技术中的光标(cursor),迭代器最早出现在1974年设计的CLU编程语言中。
如果没有写过c或者c++直接看这个解释可能很抽象,那我就直接说一个在lua中的应用,比如 pairs
函数大家都知道他是一个创建迭代器的方法,那么他实现了什么功能呢,他对我们外部隐藏了遍历的细节逻辑,然后每次调用迭代器都返回一个新的对象,就像上文所说 用户可在容器对象(例:table表)上遍访的对象,设计人员使用此接口无需关心容器对象的内存分配的实现细节(table表内部数据存储格式对外隐藏)。
迭代器在lua中的应用
在lua中最常用的两个迭代器函数为 pairs
和 ipairs
让我们看一下官方对他的定义
ipairs (t)
返回三个值(迭代函数、表 t 以及 0 ), 如此,以下代码
for i,v in ipairs(t) do body end
将迭代键值对(1,t[1]) ,(2,t[2]), … ,直到第一个空值。
pairs (t)
如果 t 有元方法 __pairs, 以 t 为参数调用它,并返回其返回的前三个值。
否则,返回三个值:next 函数, 表 t,以及 nil。 因此以下代码
for k,v in pairs(t) do body end
能迭代表 t 中的所有键值对。
通常我们配和lua通用的 for
来使用他,一般是写成下面这样
for k, v in ipairs(t) do
print(k, v)
end
不能不说现在的编程语言都在为程序员谋福址,我们已经不需要关注到下层的管理逻辑,只需要调用一下 ipairs
函数就能遍历出里面的kv内容,那么下节就让我们来自定义迭代器的实现吧,我们也能写出很优雅的代码。
自定义迭代器
那么就让我们仿照 ipairs
和 for
的形式写一个,
实现逻辑
--- 这是一个仿照 ipairs的逻辑,他规定了迭代方式,会生成一个迭代器
local function ipairs_test(t)
local index = 0
return function(t)
index = index + 1
if not t[index] then
return nil
end
return index, t[index]
end, t, index
end
测试代码
--- 自定义的数据源
local data = {1, 2, 3, 4}
--- 测试
for k, v in ipairs_test(data) do
print(k, v)
end
测试结果
1 1
2 2
3 3
4 4
好了现在上面这个函数的功能和 ipairs
一样了,但是他不能进行迭代,他还缺少一个 for
,就是可以对他进行迭代的方法,让我们来模拟一下 for
的实现,他大概长这样。
实现逻辑
--- 仿照 for 写的逻辑,
local function for_test(func_in, content_func)
local func, t, index = func_in()
repeat
local index, element = func(t)
if element ~= nil then
content_func(index, element)
end
until element == nil
end
测试代码
--- 自定义的数据源
local data = {1, 2, 3, 4}
--- 测试
for_test(
function()
return ipairs_test(data)
end,
function(k, v)
print(k, v)
end
)
测试结果
1 1
2 2
3 3
4 4
以上就实现了类似lua自带的迭代方式了,核心就是保存一个游标变量在闭包中
结语
那么今天就教程就到这里结束了,如果觉得我说的有用的话就在我的>>>>>> 戳这里 github项目<<<<<<点上一个小小的star吧,咖啡就不用请我喝了,屑屑(比心)