Lua尾调用vs循环

时间:2012-07-20 20:03:02

标签: loops lua 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

我会问以下问题:

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

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

    repeat
      io.write ('% ')
      local cmd = io.read()
    
      -- do stuff
    until cmd == 'quit'
    
  3. 在Lua中编程

      

    尾部调用是一个打扮成电话的goto。

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

  4. 谢谢。

1 个答案:

答案 0 :(得分:10)

  

是否正确使用/实现尾部呼叫消除?

如果您根据Lua语法the answer is yes询问最后对shell的调用是否是正确的尾调用。

  

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

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

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

  

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

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

但是,如果你想要一个客观的性能问题,请考虑这一点:尾部调用永远不会比循环更快。你在性能方面取得的绝对最佳成绩是相同的。

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

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

  

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

见上文。