Lua尾调用vs循环

dav*_*ave 2 lua loops tail-call-optimization

我在Lua中编写了一个CLI模块,嵌入到C程序中.

我想知道什么是处理提示的最佳方法,在尾调用循环之间进行选择.

作为尾部调用我会做这样的事情:

call = { help=function () print 'just ask politely' end }

function shell ()
  io.write ('% ')
  local cmd = io.read ()

  if cmd ~= 'quit' then      
    call[cmd] () -- for simplicity assume call[cmd] is never nil
    return shell ()
  end
end
Run Code Online (Sandbox Code Playgroud)

我会问以下问题:

  1. 它是否正确使用/实现尾部调用消除?是否call[cmd] ()在堆栈中引入任何干扰,以便我不会利用尾部消除功能

  2. 使用如下循环更好吗?如果是,为什么?

    repeat
      io.write ('% ')
      local cmd = io.read()
    
      -- do stuff
    until cmd == 'quit'
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在Lua的编程中说明了

    尾调用是打扮成一个呼叫跳转.

    那么尾调用和循环之间有什么具体的区别吗?

谢谢.

Nic*_*las 10

它是否正确使用/实现尾部调用消除?

如果你shell根据Lua语法询问最后的调用是否是正确的尾调用,答案是肯定的.

call [cmd]()是否会在堆栈中引入任何干扰,这样我就不会利用尾部调用消除?

函数调用不会以您的思维方式修改堆栈.在Lua中,尾调用的唯一要求是它具有形式return Function(params),没有额外的返回值不是函数的返回值.

正确的尾调甚至不需要自己调用; 它不需要递归.

使用如下循环更好吗?如果是,为什么?

这是一个主观点.就个人而言,我会说循环更清楚正在发生什么.

但是,如果你想要一个客观的性能问题,请考虑这一点:尾调用永远不会比循环更快.在性能方面你所获得的绝对最佳是平等的.

它可能不会那样.Lua尾调用"优化"只是意味着它重用当前函数的堆栈条目.Lua仍然需要从全局表中获取该函数.Lua仍然需要完成调用函数的所有开销; 它只是没有分配更多的堆栈内存.

它实际上是关于不会溢出堆栈而不是在不必要时分配内存.

尾调用和循环之间有什么具体的区别吗?

往上看.