【问题标题】:lua variables scopelua 变量范围
【发布时间】:2012-05-18 14:48:10
【问题描述】:

我知道还有其他类似的主题,但找不到我的问题的直接答案。

假设你有这样一个函数:

function aFunction()
  local aLuaTable = {}
  if (something) then
     aLuaTable = {}
  end
end

对于if语句里面的aLuaTable变量,还是局部的吧?基本上我要问的是,如果我第一次将一个变量定义为本地变量,然后我一次又一次地使用它,它会在程序的剩余生命周期中保持本地状态,这究竟是如何工作的?。

另外,我阅读了 Lua 全局变量的这个定义:

任何不在定义块中的变量都被称为在全局范围内。 所有内部范围都可以访问全局范围内的任何内容。

不在定义的块中是什么意思?我的理解是,如果我在任何地方“声明”一个变量,它将始终是全局的,这是不正确的吗?。

对不起,如果问题太简单了,但是来自Java和objective-c,lua对我来说很奇怪。

【问题讨论】:

  • 没有很多 XP 与 lua,但据我所知,该变量将在该函数的范围内 - 它将超出该函数的范围。在函数体(定义的块)之外声明的任何变量都被视为在全局范围内,并且可以从该 lua 脚本中的任何位置访问

标签: variables scope lua global-variables


【解决方案1】:

“任何不在定义块中的变量都被称为在全局范围内。”

这是完全错误的,所以你的困惑是可以理解的。看起来你是从用户 wiki 那里得到的。我刚刚用更正信息更新了页面:

任何未定义为 local 的变量都是全局变量。

我的理解是,如果我在任何地方“声明”一个变量,它将始终是全局的

如果您不将其定义为local,它将是全局的。但是,如果您随后创建一个具有相同名称的 local,它将优先于全局(即 Lua 在尝试解析变量名称时首先“看到”本地变量)。请参阅本文底部的示例。

如果我第一次将一个变量定义为本地变量,然后我一次又一次地使用它,它将在程序的剩余生命周期中保持本地,这是如何工作的?

当您的代码被编译时,Lua 会跟踪您定义的任何局部变量,并知道哪些变量在给定范围内可用。每当您读/写变量时,如果在范围内有一个具有该名称的本地变量,就会使用它。如果没有,则读/写(在编译时)转换为表读/写(通过表 _ENV)。

local x = 10 -- stored in a VM register (a C array)
y = 20       -- translated to _ENV["y"] = 20

x = 20       -- writes to the VM register associated with x
y = 30       -- translated to _ENV["y"] = 30

print(x)     -- reads from the VM register
print(y)     -- translated to print(_ENV["y"])

局部变量是词法范围的。其他所有内容都进入_ENV。

x = 999

do -- create a new scope
    local x = 2
    print(x)      -- uses the local x, so we print 2
    x = 3         -- writing to the same local
    print(_ENV.x) -- explicitly reference the global x our local x is hiding
end

print(x) -- 999

【讨论】:

  • 请注意_ENV 仅适用于 Lua 5.2。在 Lua 5.1(及之前)中,全局变量存储在 _G 中(实际上它比这要复杂一些,您可以更改函数的环境等)。
  • 我考虑过提及 _G(这是 5.1 中的全局状态和 5.2 中 _ENV 的默认值),但我认为这只会令人困惑。 5.2 是最新版本,所以我选择了 _ENV。除了 5.1 中的 _ENV 引用将是 _G 引用之外,有关范围的所有信息都是相同的。
  • 嗨@Mud,很抱歉插嘴。我有一个基于这种困惑的问题。我有一个嵌套的if。我想在第一层使用的第二个if 层中有一个变量。我必须求助于全局变量,还是有一些方法可以在本地使用它?我在这里提交了一个问题:stackoverflow.com/questions/60855258/…
【解决方案2】:

对于if语句里面的aLuaTable变量,还是局部的吧?

我不明白你在这里是怎么混淆的;该规则与 Java 完全相同。该变量仍在范围内,因此它继续存在。

local 变量相当于在 Java 中定义“堆栈”变量。该变量存在于定义它的块范围内,并在该块结束时不再存在。

考虑以下 Java 代码:

public static void main()
{
  if(...)
  {
    int aVar = 5; //aVar exists.
    if(...)
    {
      aVar = 10; //aVar continues to exist.
    }
  }

  aVar = 20; //compile error: aVar stopped existing at the }
}

“全局”只是非本地的任何变量名。考虑与上述等效的 Lua 代码:

function MyFuncName()
  if(...) then
    local aVar = 5 --aVar exists and is a local variable.

    if(...) then
      aVar = 10 --Since the most recent declaration of the symbol `aVar` in scope
                --is a `local`, this use of `aVar` refers to the `local` defined above.
    end
  end

  aVar = 20 --The previous `local aVar` is *not in scope*. That scope ended with
            --the above `end`. Therefore, this `aVar` refers to the *global* aVar.
end

Java 中的编译错误是完全有效的 Lua 代码,尽管它可能不是您想要的。

【讨论】:

    猜你喜欢
    • 2017-10-20
    • 1970-01-01
    • 2017-03-05
    • 2010-11-04
    • 1970-01-01
    • 2018-08-25
    • 1970-01-01
    • 2020-08-10
    相关资源
    最近更新 更多