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

时间:2014-05-27 17:22:01

标签: lua block scoping

我一直在努力为此找到答案但却没有这样做。我想知道,实际使用的do-end块是什么?它只是说在我的书中需要时使用值,所以我怎么能用它?

我是否通过在do-end循环中放置一个函数来使用它来减少局部变量的范围,并将局部变量放在函数之外但是在这个do-end块内部并且函数会看到变量?但是这个功能还可以被调用吗?

抱歉非常模糊。我希望这是有道理的。也许一个插图的例子可能有用^^

3 个答案:

答案 0 :(得分:16)

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

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

当谈到局部变量时,Lua使用标准的词法范围,正如Lua中的编程的section 4.2中所解释的那样。由于以下几个原因,词汇范围非常有用:

  • 变量作用域是静态的。您只需查看源代码,您的代码中的每个标识符对应哪些变量和函数。这与您在Bash中找到的动态范围或通过方法调用或数组查找进行间接调度相反,您需要考虑程序的执行流程以了解最终会得到什么值。

  • 变量范围有限,这有助于提高可读性并避免一些错误:

    • 如果仅在需要使用变量时声明变量,则可以声明变量并同时对其进行初始化。另一方面,如果您在函数顶部声明所有变量,那么在初始化之前可能会意外地使用一个变量。

    • 如果在内部范围内定义变量,则无法在外部范围内意外使用该变量。

  • 当您将它与嵌套函数(闭包)结合使用时,词法作用域会启用一些very expressive idioms

通常,您不必担心自己指定变量范围。函数,循环和条件会自动引入新的范围,这通常足以为变量提供良好的约束范围。也就是说,每隔一段时间,您可能想要凭空引入一些额外的范围,我们可以使用do-end。编程Lua有以下示例,您想要计算二次方程的解,并且计算有一些临时性:

do
  local a2 = 2*a
  local d = sqrt(b^2 - 4*a*c)
  x1 = (-b + d)/a2
  x2 = (-b - d)/a2
end          -- scope of `a2' and `d' ends here
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) -- OOPS! I wanted to say "print(a)"

也就是说,do-end并不需要经常使用。如果代码块很小,则不需要隐藏局部变量,如果代码块很大,通常是将代码块放在自己的子程序中的更好方法。我发现do-end闪耀的时候是你只需要进行一次计算 - 可能会多次调用函数但是如果你使用do-end块你明确表示你只运行那段代码一次。

答案 1 :(得分:10)

是的,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
    
  4. 在这三种情况下,您仍然可以在关闭该区块后致电func(),但a仅来自该功能的visible,而不是其他任何地方。

答案 2 :(得分:9)

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

do

  local i = 0

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

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

end