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

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)

输出是函数返回的函数的连续调用次数,这些函数返回'nil',直到'load()'放弃并返回一个什么也不返回的函数。

如果文档面值接受,人们会期望输出为“1”。然而,输出为“3”。这意味着load()在返回nil之前,可以调用参数三次。

另一方面,如果代码块函数立即返回字符串,然后在随后的调用中返回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()的一个错误吗? (看起来似乎是故意的,但我找不到任何解释为什么的文档。)

点赞
用户1442917
用户1442917

我得到的结果和你的有些许不同,但仍然和文档所示的不完全相同:

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-05 21:41:02
用户343123
用户343123

这是 5.1 版本中的一个错误。已经在 5.2 中进行了更正,但我们未能将更正纳入 5.1 版本。

2013-06-06 13:23:20