5

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

假设您有一个函数,例如:

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

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

此外,我阅读了 Lua 全局变量的定义:

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

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

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

4

2 回答 2

13

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

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

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

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

如果您不将其定义为local,它将是全局的。但是,如果您随后创建local具有相同名称的 a,它将优先于全局(即 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
于 2012-05-18T17:05:44.817 回答
4

对于 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 代码,尽管它可能不是您想要的。

于 2012-05-18T15:17:14.120 回答