加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

与Lua中的debug.getlocal混淆

发布时间:2020-12-14 21:44:37 所属栏目:大数据 来源:网络整理
导读:我看到 here如何使用Lua(5.1)中的debug.getlocal函数在表中插入局部变量. function locals() local variables = {} local idx = 1 while true do local ln,lv = debug.getlocal(2,idx) if ln ~= nil then variables[ln] = lv else break end idx = 1 + idx e
我看到 here如何使用Lua(5.1)中的debug.getlocal函数在表中插入局部变量.

function locals()
   local variables = {}
   local idx = 1
   while true do
     local ln,lv = debug.getlocal(2,idx)
     if ln ~= nil then
       variables[ln] = lv
     else
       break
     end
     idx = 1 + idx
   end
   return variables
 end

但是,当我尝试返回创建的表并访问它的条目时,它不起作用.

function test1()
    local v = 'I am a local!'
    return locals()
end

print(test1().v) -- nil

在一些跟踪和错误之后,我注意到在返回之前将表绑定到变量,或者只是添加括号来修复行为:

function test2()
    local v = 'I am a local!'
    return (locals())
end

print(test2().v) -- 'I am a local!'

这让我非常困惑.为什么这两个程序有任何不同之处?我不明白的是什么? locals()处于尾部呼叫位置的事实是否有所不同?

解决方法

我想让你困惑的是lua的 proper tail call功能.

为了理解这一点,我们修改了locals函数,使其接受一个参数作为调用debug.getlocal时使用的级别堆栈. (我正在使用Lua 5.3.3)

-- Get local variables with stack level 'level'.
function locals(level)
    local variables = {}
    local idx = 1
    while true do
        local ln,lv = debug.getlocal(level,idx)
        if ln ~= nil then
            variables[ln] = lv
        else
            break
        end
        idx = 1 + idx
    end
    return variables
end

然后我们修改你的测试函数,添加相同的参数,并添加一个test3函数以供参考.

function test1(level)
    local v = 'I am a local!'
    return locals(level)
end

function test2(level)
    local v = 'I am a local!'
    return (locals(level))
end

function test3(level)
    local v = 'I am a local!'
    local a = locals(level)
    return a
end

最后,我们添加一些代码来运行测试.

local function printTable(t)
    -- print(t)
    for k,v in pairs(t) do
        print(string.format("key = %s,val = %s.",k,v))
    end
end

for level = 1,3 do
    print("==== Stack level: " .. tostring(level))
    for num = 1,3 do
        print(string.format("What test%d returns: ",num))
        printTable(_G[(string.format("test%d",num))](level))
        print("")
    end
end

上面的代码运行具有不同堆栈级别的测试函数,并打印返回的键值对.我的结果如下:

==== Stack level: 1
What test1 returns: 
key = variables,val = table: 0x7fa14bc081e0.
key = idx,val = 3.
key = level,val = 1.

What test2 returns: 
key = variables,val = table: 0x7fa14bc08220.
key = idx,val = 1.

What test3 returns: 
key = variables,val = table: 0x7fa14bc088b0.
key = idx,val = 1.

==== Stack level: 2
What test1 returns: 
key = (for step),val = 1.
key = (for limit),val = 3.
key = (for index),val = 1.
key = level,val = 2.
key = printTable,val = function: 0x7fa14bc08360.
key = (*temporary),val = function: 0x7fa14bc08360.
key = num,val = 1.

What test2 returns: 
key = level,val = 2.
key = v,val = I am a local!.

What test3 returns: 
key = level,val = I am a local!.

==== Stack level: 3
What test1 returns: 
key = (*temporary),val = function: 0x109f5a070.

What test2 returns: 
key = (for step),val = 2.
key = level,val = 3.
key = printTable,val = 2.

What test3 returns: 
key = (for step),val = 3.

当level为1时,locals可以很好地给出它自己的局部变量.但是当level为2时,test1返回外部作用域的变量,而test2和test3给出你期望的结果.对于堆栈级别3,test2和test3在堆栈级别2返回类似test1的内容.因此,似乎test1跳过堆栈级别,我能想到的唯一解释是正确的尾部调用.

根据PIL(我在开头提供的链接),正确的尾调用永远不会导致堆栈溢出,我采用一些内联方式进行调用.如果我是对的,这解释了test1的return语句的跳过行为,因为这是一个正确的尾调用,并且是3个测试函数中唯一的一个.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读