为什么要使全局 Lua 函数成为本地函数?
我一直在看一些Lua源代码,我经常在文件的开头看到这样的东西:
local setmetatable, getmetatable, etc.. = setmetatable, getmetatable, etc..
它们是否只是将函数本地化,以便让Lua在经常使用时更快地访问它们?
I've been looking at some Lua source code, and I often see things like this at the beginning of the file:
local setmetatable, getmetatable, etc.. = setmetatable, getmetatable, etc..
Do they only make the functions local to let Lua access them faster when often used?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
本地数据位于堆栈上,因此访问速度更快。但是,我严重怀疑
setmetatable
的函数调用时间对于某些程序来说实际上是一个重要问题。对此可能的解释如下:
防止污染全球环境。现代 Lua 模块约定是不让它们直接将自己注册到全局表中。他们应该构建一个本地函数表并返回它们。因此,访问它们的唯一方法是使用局部变量。这迫使许多事情发生:
一个模块不能意外覆盖另一个模块的功能。
如果模块无意中执行了此操作,则该模块返回的表中的原始函数仍然可以访问。只有使用
local modname = require "modname"
才能保证您准确且仅获得该模块公开的内容。包含其他模块的模块不能相互干扰。从
require
返回的表始终是模块存储的内容。由读过“
本地
变量访问速度更快”的人进行的过早优化,然后决定将所有内容都本地
。一般来说,这是一个很好的做法。好吧,除非是因为#2。
Local data are on the stack, and therefore they do access them faster. However, I seriously doubt that the function call time to
setmetatable
is actually a significant issue for some program.Here are the possible explanations for this:
Prevention from polluting the global environment. Modern Lua convention for modules is to not have them register themselves directly into the global table. They should build a local table of functions and return them. Thus, the only way to access them is with a local variable. This forces a number of things:
One module cannot accidentally overwrite another module's functions.
If a module does accidentally do this, the original functions in the table returned by the module will still be accessible. Only by using
local modname = require "modname"
will you be guaranteed to get exactly and only what that module exposed.Modules that include other modules can't interfere with one another. The table you get back from
require
is always what the module stores.A premature optimization by someone who read "
local
variables are accessed faster" and then decided to make everythinglocal
.In general, this is good practice. Well, unless it's because of #2.
除了 Nicol Bolas 的回答之外,我还要补充第三点:
如果函数已从沙箱中排除并且代码是从沙箱内加载的,那么它将无法工作。但是,如果首先加载代码,则沙箱可以调用加载的代码,并能够从沙箱中排除 setmetatable 等。
In addition to Nicol Bolas's answer, I'd add on to the 3rd point:
If the functions have been excluded from the sandbox and the code is loaded from within the sandbox, then it won't work. But if the code is loaded first, the sandbox can then call the loaded code and be able to exclude setmetatable, etc, from the sandbox.
我这样做是因为它允许我查看每个模块使用的功能
此外,它还可以保护您免受其他人更改全局环境中的功能的影响。
这是一个免费的(过早的)优化是一个好处。
I do it because it allows me to see the functions used by each of my modules
Additionally it protects you from others changing the functions in global environment.
That it is a free (premature) optimisation is a bonus.
另一个微妙的好处:它清楚地记录了模块导入了哪些变量(函数、模块)。如果您使用 module 语句,它会强制执行此类声明,因为全局环境被替换(因此全局变量不可用)。
Another subtle benefit: It clearly documents which variables (functions, modules) are imported by the module. And if you are using the module statement, it enforces such declarations, because the global environment is replaced (so globals are not available).