6

来自Lua 5.1 文档load()

使用函数加载块func以获取其片段。每次调用都func必须返回一个与先前结果连接的字符串。返回空字符串、nil或无值表示块的结束。

根据我的测试,这实际上不是真的。或者,更确切地说,文档至少具有误导性。

考虑这个示例脚本:

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)

输出是对在放弃之前返回的函数make_loader()返回的函数的连续调用次数,并返回一个不返回任何内容的函数。nilload()

如果要按面值获取文档,人们会期望此处的输出为“1”。但是,输出为“3”。这意味着调用 to 的参数load()直到它返回nil 3 次load()放弃。

另一方面,如果块函数立即返回一个字符串,然后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()吗?(这似乎是故意的,但我找不到任何解释原因的文档。)

4

2 回答 2

6

这是 5.1 中的错误。它已在 5.2 中更正,但我们未能将更正合并到 5.1 中。

于 2013-06-06T13:23:20.417 回答
3

我得到的结果与你的略有不同,但它们仍然不是文档所暗示的:

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,第二次是 nil。因为2它被调用了三次,因为第一次是nil, 然后return true, 然后再nil一次。对于所有其他值,它被调用了两次:似乎第一个nil被忽略了,并且该函数至少被再次调用了一次。

如果确实如此,则文档需要反映这一点。我查看了源代码,但没有看到任何可以解释为什么第一个返回nil被忽略的东西(我也用空字符串进行了测试,没有值具有相同的结果)。

于 2013-06-05T21:41:02.223 回答