Подтвердить что ты не робот

Оптимизация хвостовых вызовов в lua

Lua утверждает, что он правильно реализует хвостовой вызов, поэтому для каждого вызова не требуется поддерживать стеки, таким образом, он позволяет бесконечную рекурсию, я пытался написать функцию суммы, один из них не является хвостовым вызовом, а один - хвостовым вызовом:

версия без хвоста

function sum(n)
    if n > 0 then
        return n + sum(n-1)
    end
end

print(sum(1000000))

stackoverflow как ожидалось.

версия tailcall

function sum2(accu, n)
    if n > 0 then
        accu.value = accu.value + n
        sum2(accu, n-1)
    end
end
local accu = {value = 0}
sum2(accu, 1000000)
print(accu.value)

Я предполагаю, что в этом случае не было бы stackoverflow, поскольку это tailcall, но он все еще не удалось из-за stackoverflow:

/bin/lua/5.1.4/bin/lua: tailcall.lua:13: stack overflow
stack traceback:
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        ...
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:13: in function 'sum2'
        tailcall.lua:17: in main chunk
        [C]: ?

Итак, lua действительно поддерживает оптимизацию хвостовых вызовов, или моя функция на самом деле не является хвостом здесь?

Я использую lua 5.1.4 на redhat 5

4b9b3361

Ответ 1

Хвост в Lua должен иметь следующую форму

return fct(args)

Итак, версия вашего хвоста должна быть переписана как:

function sum2(accu, n)
  if n > 0 then
    accu.value = accu.value + n
    return sum2(accu, n-1) --< note the return here
  end
end