2

我正在用 Lua 编写一个小 CLI 模块以嵌入到 C 程序中。

我想知道处理提示的最佳方法是什么,在tail-callloop之间进行选择。

作为尾声,我会做这样的事情:

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 编程中说明

    tail call是一个装扮成呼叫的 goto。

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

谢谢你。

4

1 回答 1

10

它是尾调用消除的正确使用/实现吗?

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

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

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

一个适当的尾调用甚至不必调用它自己;它不需要是递归的。

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

这是一个主观的观点。就个人而言,我会说循环对正在发生的事情更加清楚。

但是,如果您想要一个客观的性能问题,请考虑这一点:尾调用永远不会比循环快。就性能而言,您将获得的绝对最佳值是相等的。

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

这实际上是关于不溢出堆栈并且在不必要时不分配内存。

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

往上看。

于 2012-07-20T20:16:07.890 回答