首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有可用于访问Lua中的局部变量的表?

是否有可用于访问Lua中的局部变量的表?
EN

Stack Overflow用户
提问于 2016-11-28 06:09:55
回答 1查看 3K关注 0票数 4

就像我们如何做到这一点:

代码语言:javascript
复制
a = 3
print(_G['a']) -- 3

我想做这样的事:

代码语言:javascript
复制
local a = 3
print(_L['a']) -- 3

我基本上希望能够使用局部变量的名称作为字符串访问它们。是否有一个表可以这样做,也许可以作为函数参数传递?它将类似于this关键字在ActionScript中。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-28 06:53:59

这可以通过debug库(即getlocalsetlocal函数)来实现。如果您不能使用这个库(或访问C API),那么您就倒霉了。

您可以使用巧尽心思构建的_L表扩展全局环境,该表在访问时执行当前局部变量集的线性查找。

读取局部变量只需查找匹配的变量名,并返回其值。写入局部变量需要在堆栈帧中发现其索引,然后相应地更新值。请注意,您不能创建新的局部变量。

下面是一个使用Lua5.1(但不是Lua 5.2+)的简单示例。

代码语言:javascript
复制
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
})

在使用中:

代码语言:javascript
复制
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)的表。

如果上面使用的元数据对您来说是一个全新的主题,请参见。

在Lua 5.2+中,您可以使用特殊的_ENV表来调整当前块的环境,但请注意,这与使用local变量不同。

代码语言:javascript
复制
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)使用当地人可能不是最好的方法。

您可以在适当的情况下将变量存储在一个表中,以便以更少的开销获得相同的结果。强烈建议采用这种方法。

代码语言:javascript
复制
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

不要为了解决不必要的问题而自食其果。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40838093

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档