我正在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
我会问以下问题:
是否正确使用/实现尾部呼叫消除? call[cmd] ()
是否会在堆栈中引入任何干扰,以便我不会利用尾部调用消除?
使用如下所示的循环会更好吗?如果是,为什么?
repeat
io.write ('% ')
local cmd = io.read()
-- do stuff
until cmd == 'quit'
在Lua中编程
尾部调用是一个打扮成电话的goto。
尾部调用和循环之间有什么具体的区别吗?
谢谢。
答案 0 :(得分:10)
是否正确使用/实现尾部呼叫消除?
如果您根据Lua语法the answer is yes询问最后对shell
的调用是否是正确的尾调用。
调用[cmd]()是否会在堆栈中引入任何干扰,这样我就不会利用尾部调用消除?
函数调用不会以您的思维方式修改堆栈。在Lua中,尾部调用的唯一要求是它的形式为return Function(params)
,没有额外的返回值不是函数的返回值。
正确的尾调甚至不需要自己调用;它不需要递归。
使用如下循环更好吗?如果是,为什么?
这是一个主观点。就个人而言,我会说循环更清楚发生了什么。
但是,如果你想要一个客观的性能问题,请考虑这一点:尾部调用永远不会比循环更快。你在性能方面取得的绝对最佳成绩是相同的。
它可能不会那样。 Lua尾调用“优化”只是意味着它重用当前函数的堆栈条目。 Lua仍然需要从全局表中获取该函数。 Lua仍然需要完成调用函数的所有开销;它只是不需要分配更多的堆栈内存。
它实际上是关于不会溢出堆栈而不是在不必要时分配内存。
尾调用和循环之间有什么具体的区别吗?
见上文。