就像我们如何做到这一点:
a = 3
print(_G['a']) -- 3
Run Code Online (Sandbox Code Playgroud)
我希望能够做这样的事情:
local a = 3
print(_L['a']) -- 3
Run Code Online (Sandbox Code Playgroud)
我基本上希望能够使用它们的名称作为字符串来访问局部变量。有没有一张表可以做到这一点,也许可以作为函数参数传递一个表?就像thisActionScript中的关键字。
这可以通过debug库- getlocal和setlocal功能来实现。如果您不能使用此库(或访问C API),那么您就不走运了。
您可以使用特制的_L表来扩展全局环境,该表在被访问时会对当前的本地集执行线性查找。
读取局部变量只是找到匹配的变量名称,然后返回其值。写入局部变量要求您在堆栈帧中发现其索引,然后相应地更新该值。请注意,您不能创建新的本地人。
这是一个适用于Lua 5.1(但不适用于Lua 5.2+)的简单示例。
local function find_local (key)
local n = 1
local name, sname, sn, value
repeat
name, value = debug.getlocal(3, n)
if name == key then
sname = name
sn = n
end
n = n + 1
until not name
return sname, sn
end
_G._L = setmetatable({}, {
metatable = false,
__newindex = function (self, key, value)
local _, index = find_local(key)
if not index then
error(('local %q does not exist.'):format(key))
end
debug.setlocal(2, index, value)
end,
__index = function (_, key)
return find_local(key)
end
})
Run Code Online (Sandbox Code Playgroud)
正在使用:
local foo = 'bar'
print(_L['foo']) --> 'bar'
_L['foo'] = 'qux'
print(_L['foo']) --> 'qux'
local function alter_inside (key)
local a, b, c = 5, 6, 7
_L[key] = 11
print(a, b, c)
end
alter_inside('a') --> 11 6 7
alter_inside('b') --> 5 11 7
alter_inside('c') --> 5 6 11
Run Code Online (Sandbox Code Playgroud)
您可以使用普通函数而不是将表与读/写操作(__index,__newindex)结合使用,以不同的方式编写代码。
请参阅第2.4节-Metatables and Metamethods如果上述对元表的使用对您来说是一个全新的话题。
在Lua 5.2+中,您可以使用特殊_ENV表来调整当前块的环境,但是请注意,这与使用local变量不同。
local function clone (t)
local o = {}
for k, v in pairs(t) do o[k] = v end
return o
end
local function alter_inside (key)
local _ENV = clone(_ENV)
a = 5
b = 6
c = 7
_ENV[key] = 11
print(a, b, c)
end
alter_inside('a') --> 11 6 7
alter_inside('b') --> 5 11 7
alter_inside('c') --> 5 6 11
Run Code Online (Sandbox Code Playgroud)
最后,请注意,这种(滥用)对当地人的使用可能不是最好的方法。
您可以在适当的时候将变量简单地存储在表中,从而以更少的开销获得相同的结果。强烈建议使用此方法。
local function alter_inside (key)
-- `ls` is an arbitrary name, always use smart variable names.
local ls = { a = 5, b = 6, c = 7 }
ls[key] = 11
print(ls.a, ls.b, ls.c)
end
alter_inside('a') --> 11 6 7
alter_inside('b') --> 5 11 7
alter_inside('c') --> 5 6 11
Run Code Online (Sandbox Code Playgroud)
不要为解决不必要的问题而陷入困境。