Поведение 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)
Выходными данными является количество последовательных вызовов функции, возвращаемых make_loader()
что вернулся nil
до load()
сдается и возвращает функцию, не возвращающую ничего.
Можно ожидать, что результат здесь будет "1", если документация будет принята за чистую монету. Тем не менее, вывод "3". Это подразумевает, что аргумент load()
вызывается, пока не вернется nil
три раза до того 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()
? (Кажется, это сделано намеренно, но я не могу найти никаких документов, объясняющих почему.)
2 ответа
Это ошибка в 5.1. Это было исправлено в 5.2, но мы не смогли включить исправление в 5.1.
Я получаю немного другие результаты от ваших, но они все еще не совсем то, что подразумевает документация:
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
игнорируется и функция вызывается как минимум еще раз.
Если это действительно так, документация должна отражать это. Я посмотрел на исходный код, но не увидел ничего, что могло бы объяснить, почему первый вернулся nil
игнорируется (я также проверил с пустой строкой и без значения с тем же результатом).