就像我們如何能做到這一點:有沒有一個表可以用來訪問Lua中的局部變量?
a = 3
print(_G['a']) -- 3
我希望能夠做這樣的事情:
local a = 3
print(_L['a']) -- 3
我基本上希望能夠用自己的名字來訪問本地變量爲字符串。有沒有一個表可以做到這一點,也許可以作爲函數參數傳遞?這就像ActionScript中的this
關鍵字。
就像我們如何能做到這一點:有沒有一個表可以用來訪問Lua中的局部變量?
a = 3
print(_G['a']) -- 3
我希望能夠做這樣的事情:
local a = 3
print(_L['a']) -- 3
我基本上希望能夠用自己的名字來訪問本地變量爲字符串。有沒有一個表可以做到這一點,也許可以作爲函數參數傳遞?這就像ActionScript中的this
關鍵字。
這可以通過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
})
在使用中:
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
你可以以不同的方式寫此,使用普通的功能,而不是用表讀/寫操作(__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
最後一點,也認爲這(AB)利用當地人的可能不是最好的辦法。
在適當的情況下,您可以簡單地將變量存儲在表中,以獲得相同的結果,而且開銷要小得多。強烈建議使用這種方法。
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
不要挖你一個洞,試圖解決不必要的問題。
你的代碼不起作用。 '本地a = 1; print(a,_L ['a']) - > 1 nil' –
看起來像Lua 5.1和5.2+之間的差異,大概是由於本地環境的不同。我在整個答案中鏈接了5.3文檔,但承認只在5.1中測試過這些代碼。我沒有精力讓這些代碼在各個版本之間移植,如果它甚至可能的話,考慮到它只是一個理論上可能的簡單例子。同樣,建議不要在生產中使用這種內省編程。該手冊警告不要使用除調試以外的其他任何調試庫,因爲它跟蝸牛一樣慢。 – Oka
您可以請求解決方案上方的警告。這不僅僅是壞習慣 - 由於很多原因,這很可怕,因爲你可能認識你自己。 –
請避免這樣做。我知道它可能看起來很刺耳,但通常有更好的方法來做你想在Lua中做的事情,而不是使用調試庫。請避免[XY問題](http://meta.stackexchange。com/questions/66377/what-the-xy-problem) – ATaco
http://hawwashsoft.proboards.com/thread/64/locals – warspyking