为啥在 Lua 中使用 do-end 块?

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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 块可以用来限制变量的范围;要使使用这些变量的函数保持可见,您有多种选择

    本地化使函数保持在块外的变量:

    local func    
    do
      local a = 0
      func = function(inc)
        a = a + inc
        return a
      end
    end
    

    使用全局函数:

    do
      local a = 0
      function func(inc)
        a = a + inc
        return a
      end
    end
    

    使用方法:

    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

【讨论】:

以上是关于为啥在 Lua 中使用 do-end 块?的主要内容,如果未能解决你的问题,请参考以下文章

Rbx.Lua - 为啥这个 Color3 不接受 VertexColor?

为啥在 Lua 中使用本地需求?

为啥lua语言中使用全局变量就会造成内存泄漏

为啥lua语言中使用全局变量就会造成内存泄漏呢??

为啥我的 LUA 解释器不能处理字符串键值?

lua解释器 是啥东西? lua 后面加lua文件名为啥不行?