Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function 为什么要将全局Lua函数本地化?_Function_Scope_Lua - Fatal编程技术网

Function 为什么要将全局Lua函数本地化?

Function 为什么要将全局Lua函数本地化?,function,scope,lua,Function,Scope,Lua,我一直在看一些Lua源代码,我经常在文件开头看到这样的内容: local setmetatable, getmetatable, etc.. = setmetatable, getmetatable, etc.. 它们是否只使函数成为本地函数,以便Lua在经常使用时更快地访问它们?本地数据位于堆栈上,因此它们访问它们的速度更快。然而,对于某些程序来说,setmetatable的函数调用时间实际上是一个重要问题,对此我深表怀疑 以下是对此的可能解释: 防止污染全球环境。模块的现代Lua约定是不让

我一直在看一些Lua源代码,我经常在文件开头看到这样的内容:

local setmetatable, getmetatable, etc.. = setmetatable, getmetatable, etc..

它们是否只使函数成为本地函数,以便Lua在经常使用时更快地访问它们?

本地数据位于堆栈上,因此它们访问它们的速度更快。然而,对于某些程序来说,
setmetatable
的函数调用时间实际上是一个重要问题,对此我深表怀疑

以下是对此的可能解释:

  • 防止污染全球环境。模块的现代Lua约定是不让它们自己直接注册到全局表中。他们应该构建一个本地函数表并返回它们。因此,访问它们的唯一方法是使用局部变量。这迫使人们做很多事情:

  • 一个模块不能意外覆盖另一个模块的功能

  • 如果某个模块意外地执行了此操作,则仍可访问该模块返回的表中的原始函数。只有通过使用
    local modname=require“modname”
    才能保证您获得该模块公开的内容

  • 包含其他模块的模块不能相互干扰。从
    require
    返回的表始终是模块存储的表

  • 有人读到“
    local
    变量访问速度更快”,然后决定将所有内容都设置为
    local
    ,这是一种过早的优化


  • 一般来说,这是一种良好的做法。除非是因为#2。

    我这样做是因为它允许我查看每个模块使用的函数

    此外,它还可以防止其他人在全局环境中更改功能。
    这是一个免费的(过早的)优化,这是一个额外的好处。

    除了Nicol Bolas的答案,我还要补充第三点:

    • 它允许您的代码在加载后从沙箱中运行

    如果函数已从沙盒中排除,并且代码是从沙盒中加载的,那么它将无法工作。但如果先加载代码,沙盒就可以调用加载的代码,并能够从沙盒中排除setmetatable等。另一个微妙的好处是:它清楚地记录了模块导入的变量(函数、模块)。如果您使用的是module语句,它将强制执行此类声明,因为全局环境已被替换(因此全局函数不可用)。

    您可能想看看没有什么可以阻止您的模块使用不在该列表中的函数。因此,如果您突然需要一个全局函数,而忘记将其添加到列表中,那么您使用的是全局函数。此外,如果有人更改了全局函数,那么他们这样做可能有很好的理由,比如监控某些函数的使用等等;我有一个pre-commit钩子,它使用luac搜索GETGLOBAL操作码并向我发出警告。实现这么简单的东西需要做很多工作。您刚刚使用环境为每个函数提供了特定的全局空间,因此它们不会影响其他人的。Lua书中的编程告诉你如何做到这一点;特别是在大型程序或编写库时;即使被限制在环境中。通过检查GETGLOBAL,我还经常发现在重构过程中遗漏了打字错误和代码;总的来说,这是一种更好的编码方式。同样,可以通过设置适当的环境来保护全局代码。通过编译的源代码解析某些特定操作码要比正确设置环境困难得多。另外,你不必在你所有的脚本中都插入一个巨大的序言。使认为调用内置程序(如rawset或ipairs)不好的linter静音。