为什么Lua禁止在局部变量定义之后使用goto?

我从手册 http://lua-users.org/wiki/GotoStatement 上读到了这个内容。

我在一个循环中有一个类似的代码块:

while true do
  if someCond == nil then
      goto f  -- 无效 (向本地定义的范围进行前向跳转)
  end

  local x = 1
   -- 做一些 x 的操作
  ::f::
end

这将失败并显示“...跳转到本地 x 的范围内”

但是为什么?如果执行了跳转,它是在任何使用本地 x 的之后 - 它不再被触及 - 因此在此处不再需要“本地 x”

当我将本地 x 替换为只是 x = 1(变成全局变量)时,它可以正常工作。

这是一个疏漏还是一种缺失的优化?例如,也许他们总是假设本地变量在跳转到标签后可能仍然被使用。

点赞
用户582
用户582

我不太确定本地变量是如何注册的,但是它们是通过数值索引引用的。假设如果使用 goto 跳过一个本地变量的定义,则该本地变量将永远不会被创建,因此任何在标签之后尝试访问该本地变量的人都将尝试使用无效的索引。

你是对的,理论上,如果在标签之后从未使用过本地变量,则不一定必须阻止跳转,但实际上,Lua 本地变量存活时间为其作用域的结束,而非仅仅是在最后一次使用之后就过期。任何形式的动态代码执行都需要这一点成立。

但是,你可以使用 do-块来限制本地变量的作用域。在你的代码中,你应该重写为:

while true do
  if someCond == nil then
      goto f
  end

  do
      local x = 1
       -- do something with x
  end -- x is now gone
  ::f::
end
2013-01-24 23:53:33