lua for循环的陷阱

lua和C一样提供for循环,但是lua的for不同于C的for,有些地方甚至可以称之为陷阱:昨天在用lua编写一个测试demo时就遇到了。 现在来详细说说昨天遇到的奇怪现象。示例如下:

local t = {1,0,2,0,3,0,4}
for i = 1, #t do
    while i <= #t and t[i] == 0 do
        i = i + 1
    end
    if i > #t then
        break
    end
    print(t[i])
end

打印结果预期的是:

1
2
3
4

但实际上是:

1
2
2
3
3
4
4

也就是说,for循环中的while循环跳过0失败了。为什么会这样呢?循环变量i的值不是被while循环修改了吗?这个问题也让我昨天晚上困惑了一段时间,接着去查阅了lua53的参考手册并阅读lua虚拟机实现源码中关于for的部分,才恍然大悟。 lua的for和C中的for是不同的,实际上你不能修改lua的for循环中的循环变量的值,正如上述代码,修改的实际是i的一个副本,而i的值只会被for修改,也就是说for v = e1, e2, e3 do block end等价代码(来自lua53参考手册):

do
    local var, limit, step = tonumber(e1), tonumber(e2), tonumber(3)
    if not (var and limit and step) then
        error()
    end
    var = var - step
    while true do
        var = var + step
        if (step >= 0 and var > limit) or (step < 0 and var < limit) then
            break
        end
        local v = var
        block
    end
end    

此等价代码和lua虚拟机中实现的C代码大致类似。在for循环中去修改循环变量var的值,实际上是修改的var的副本v的值,这就是为什么在for循环中while i <= #t and t[i] == 0 then i = i + 1 end不能真正的修改循环变量i的值。 记住lua for循环的特点,不要踩中这个陷阱。