当块函数返回nil时load()的行为

来自Lua 5.1 documentation for load()

使用函数func加载一个块来获取它的碎片 . 每次调用func都必须返回一个与之前结果连接的字符串 . 返回空字符串,nil或no值表示块的结尾 .

从我的测试来看,这实际上并非如此 . 或者说,文档至少具有误导性 .

考虑这个示例脚本:

function make_loader(return_at)
    local x = 0

    return function()
        x = x + 1

        if x == return_at then return 'return true' end

        return nil
    end
end

x = 0
repeat
    x = x + 1
until not load(make_loader(x))()

print(x)

输出是在 load() 放弃之前返回 nilmake_loader() 返回的函数的连续调用次数,并返回一个不返回任何函数的函数 .

如果要按面值采用文档,可以预期此处的输出为"1" . 但是,输出是"3" . 这意味着 load() 的参数被调用,直到它在 load() 放弃之前返回 nil 三次 .

另一方面,如果chunk函数立即返回一个字符串,然后在后续调用中返回 nil ,则只需要一个 nil 来停止加载:

function make_loader()
    local x = 0

    return {
        fn=function()
            x = x + 1

            if x == 1 then return 'return true' end

            return nil
        end,
        get_x=function() return x end
    }
end

loader = make_loader()
load(loader.fn)
print(loader.get_x())

按照我的预期打印“2” .

所以我的问题是:文档错了吗?出于某种原因,这种行为是否可取?这只是 load() 中的一个错误吗? (这似乎是故意的,但我找不到任何解释原因的文件 . )

回答(2)

2 years ago

这是5.1中的错误 . 它已在5.2中得到纠正,但我们未能将修正纳入5.1 .

2 years ago

我得到的结果与你的结果略有不同,但它们仍不完全符合文档的含义:

function make_loader(return_at)
    local x = 0
    return function()
        x = x + 1
        print("make_loader", return_at, x)
        if x == return_at then return 'return true' end
        return nil
    end
end

for i = 1, 4 do
    load(make_loader(i))
end

这将返回以下结果:

make_loader 1   1
make_loader 1   2
make_loader 2   1
make_loader 2   2
make_loader 2   3
make_loader 3   1
make_loader 3   2
make_loader 4   1
make_loader 4   2

因为 1 被称为两次,因为第一个是 return true 而第二个是零 . 对于 2 ,它被调用三次,因为第一个是 nil ,然后是 return true ,然后是 nil . 对于所有其他值,它被调用两次:似乎第一个 nil 被忽略,并且该函数至少被调用一次 .

如果's indeed the case, the documentation needs to reflect that. I looked at the source code, but didn't看到任何可以解释为什么第一次返回 nil 被忽略的东西(我也用空字符串测试,没有相同结果的值) .