【问题标题】:Why use a do-end block in Lua?为什么在 Lua 中使用 do-end 块?
【发布时间】:2014-07-16 17:16:18
【问题描述】:

我一直试图为此寻找答案,但未能如愿。我想知道, do-end 块实际用于什么?它只是说在我的书中需要时使用值,那么我该如何使用它呢?

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

抱歉,我说得很含糊。我希望这是有道理的。也许一个图解的例子可能有用^^

【问题讨论】:

    标签: lua block scoping


    【解决方案1】:

    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 与嵌套函数(闭包)结合使用时,词法作用域会启用一些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 块,你会清楚地表明你只是在运行那段代码一次。

    【讨论】:

      【解决方案2】:

      是的,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 只是来自该函数的visible,而不是其他任何地方。

      【讨论】:

        【解决方案3】:

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

        do
        
          local i = 0
        
          function inc()
            i = i + 1
            return i
          end
        
          function dec()
            i = i - 1
            return i
          end
        
        end
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-10-09
          • 2017-07-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-10
          • 1970-01-01
          相关资源
          最近更新 更多