gpt4 book ai didi

lua - Lua 中与 debug.getlocal 的混淆

转载 作者:行者123 更新时间:2023-12-01 22:46:08 26 4
gpt4 key购买 nike

我看到了here如何使用 Lua 中的 debug.getlocal 函数在表中插入局部变量(5.1)。

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

经过一些尝试和错误,我注意到在返回之前将表绑定(bind)到变量,或者简单地添加括号可以修复该行为:

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

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

这让我很困惑。为什么这两个程序有任何不同?我不明白什么? locals() 处于尾部调用位置这一事实有什么区别吗?

最佳答案

我猜让你感到困惑的是proper tail call lua的特点。

为了理解这一点,我们修改您的 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 = 3.
key = level, val = 1.

What test3 returns:
key = variables, val = table: 0x7fa14bc088b0.
key = idx, val = 3.
key = level, 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 = 2.
key = v, val = I am a local!.

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

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

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

level为1时,locals可以很好地给出自己的局部变量。但是当level为2时,test1返回外部作用域的变量,而test2test3给出你的结果预计。对于堆栈级别 3 test2test3 在堆栈级别 2 返回类似 test1 的内容。所以看起来 test1 跳过堆栈级别,我能想到的唯一解释是正确的尾部调用。

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

关于lua - Lua 中与 debug.getlocal 的混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38800475/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com