Lua中的generic for

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

如果你觉得我的文章有帮助,欢迎关注我的微信公众号(大龄社畜的游戏开发之路-

posted @ 2021-02-28 15:04  异次元的归来  阅读(24)  评论(0编辑  收藏  举报