在Lua中为什么要使用do-end块?

我一直试图找到关于这个问题的答案,但一直失败。我想知道,do-end块实际上是用来干什么的?我的书里只是说在需要时使用值,那我该怎么用呢?

我是不是应该把一个函数放在do-end循环中,通过在函数外部但在这个do-end块内放置局部变量来缩小局部变量的作用域,并且函数能够看到这些变量?但是,函数还能被调用吗?

很抱歉表达得非常含糊。我希望这有意义。也许一个具体的例子会更有用~~

原文链接 https://stackoverflow.com/questions/23895406

点赞
stackoverflow用户1442917
stackoverflow用户1442917

是的,do...end 块可以用于限制变量的范围;为了使使用这些变量的函数可见,您有几个选项。

  1. 将保存函数的变量本地化在块之外:

    local func
    do
      local a = 0
      func = function(inc)
        a = a + inc
        return a
      end
    end
    
  2. 使用全局函数:

    do
      local a = 0
      function func(inc)
        a = a + inc
        return a
      end
    end
    
  3. 使用方法:

    local tbl = {}
    do
      local a = 0
      function tbl:func(inc)
        a = a + inc
        return a
      end
    end
    

在这三种情况下,您仍然可以在块关闭后调用func(),但是a仅在该函数中可见,而不是在任何其他地方。

2014-05-27 17:32:41
stackoverflow用户90511
stackoverflow用户90511

do-end 块与变量作用域的问题有关。实际上,当你使用一个标识符时,它有什么值?例如,当我们编写以下程序时,会打印出什么数字?

local x = 10
if x > 0 then
    local x = 17
    print(x)
end
print(x)

对于局部变量,Lua 使用标准的词法作用域,这在《Programming in Lua》书的第 4.2 小节中解释得很好。词法作用域有几个非常有用的原因:

  • 变量作用域是静态的。通过查看源代码,您可以知道您的代码中每个标识符对应的变量和函数。这与在 Bash 中找到的动态作用域或通过方法调用或数组查找进行间接调度的情况相反,在这种情况下,您需要考虑程序的执行流程才能知道最终得到的值。

  • 变量作用域是有限的,这有助于可读性并避免一些错误:

    • 如果只有在需要使用变量时才声明变量,则可以同时声明和初始化变量。另一方面,如果在函数顶部声明所有变量,则可能会在初始化变量之前意外地使用变量。

    • 如果在内部作用域内定义变量,则不能在外部作用域中意外地使用它。

  • 词法作用域结合嵌套函数(闭包)时,启用了一些非常表达性的惯用语法。

通常,您不需要担心自己指定变量作用域。函数、循环和条件语句会自动引入新的作用域,这通常足以为您的变量提供明确的作用域。话虽如此,偶尔您可能需要在无中生有地引入一些额外的作用域,这时可以使用 do-end。《Programming Lua》有以下示例,其中您想计算二次方程的解,计算中有一些暂存变量:

do
  local a2 = 2 * a
  local d = sqrt(b^2 - 4 * a * c)
  x1 = (-b + d) / a2
  x2 = (-b - d) / a2
end          -- `a2' 和 `d' 的作用域在此处结束
print(x1, x2)

如果没有 do-end 块,则 a2d 可能在不再需要使用它们之后被意外地使用:

local a2 = 2 * a
local d = sqrt(b^2 - 4 * a * c)
x1 = (-b + d) / a2
x2 = (-b - d) / a2
print(x1, x2)

print(a2) -- 糟糕!我想说 "print(a)"

话虽如此,do-end 并不需要经常使用。如果代码块很小,隐藏局部变量的需求就不那么大;如果代码块很大,将代码块放入自己的子例程中通常是更好的方法。我觉得 do-end 突出的时候是当您只需要运行一次计算时 - 函数可能会被调用多次,但如果您使用 do-end 块,则清楚地表明您只运行一次该代码块。

2014-05-27 21:20:41
stackoverflow用户1560821
stackoverflow用户1560821

除了已经给出的好答案之外,我想提到共享一个私有变量在两个或多个函数之间的能力:

do

  local i = 0

  function inc()
    i = i + 1
    return i
  end

  function dec()
    i = i - 1
    return i
  end

end
2014-05-28 07:09:36