Lua的generic for是一个很好用的语法糖,它为我们隐藏了迭代器背后的细节,使用起来非常简单:
local l = {1, 2, 3}
for k, v in ipairs(l) do
print("k, v ", k, v)
end
local t = {["a"] = 1, ["b"] = 2, ["c"] = 3}
for k, v in pairs(t) do
print("k, v ", k, v)
end
那么ipairs,pairs这两个函数,背后究竟做了什么?我们要如何去自定义实现这类函数呢?
lua规定这类函数需要返回三个值:迭代器函数_f
,不变量_s
,以及控制变量_v
。迭代器函数_f
接收不变量_s
和控制变量_v
作为函数的参数。迭代器函数_f
可以返回若干个参数,其中第一个参数会被用来当作下一轮的控制变量_v
传给迭代器函数_f
,直到_v
为nil为止。用代码表示的话,可以写成如下的函数:
function my_generic_for(func, ...)
local f, s, v = func(...)
while true do
local v1, v2 = f(s, v)
v = v1
if not v then
break
end
print("k v", v1, v2)
end
end
我们可以调用一下试试:
my_generic_for(ipairs, {1,2,3})
my_generic_for(pairs, {['a'] = 1,['b'] = 2, ['c'] = 3})
那么,接下来让我们尝试去实现一下ipairs。ipairs用于对lua的list,即连续的数组进行迭代,从数组下标1开始,到数组元素为nil结束。有了这些特征,我们可以写一个自己的ipairs了:
function iter(s, v)
v = v + 1
if s[v] then
return v, s[v]
else
return nil
end
end
function my_ipairs(t)
local _s = t
local _f = iter
local _v = 0
-- 迭代器,不变量,变量
return _f, _s, _v
end
同样地,让我们来试试:
local l = {3, 4, 5}
for k, v in ipairs(l) do
print("k, v ", k, v)
end
类似地,我们也可以实现自己的pairs函数。pairs用到的迭代器函数是next,可以直接拿来用:
function my_pairs(t)
local _s = t
local _f = next
local _v = nil
-- 迭代器,不变量,变量
return _f, _s, _v
end
然后尝试:
local t = {["a"] = 1, ["b"] = 2, ["c"] = 3}
for k, v in my_pairs(t) do
print("k, v ", k, v)
end
如果你觉得我的文章有帮助,欢迎关注我的微信公众号(大龄社畜的游戏开发之路)-