2012-02-08 76 views
11

我一直在寻找一些Lua的源代码,我经常看到这样的事情在文件的开头:为什么要使全局Lua函数在本地?

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

难道他们只能让当地的功能,让Lua中访问他们更快时经常使用?

+1

你可能想看看http://stackoverflow.com/questions/4643814/why-would-this-lua-optimization-hack-help – 2012-02-08 22:29:38

回答

12

本地数据位于堆栈上,因此它们可以更快地访问它们。但是,我严重怀疑函数调用时间到setmetatable实际上是一些程序的重要问题。

下面是这种情况的可能的解释:

  1. 预防污染地球环境。模块的现代Lua约定是不让它们直接注册到全局表中。他们应该建立一个本地函数表并返回它们。因此,只有的方式来访问它们是一个局部变量。这迫使一些事情:

    1. 一个模块不能意外覆盖另一个模块的功能。

    2. 如果模块不小心做到这一点,模块返回的表格中的原始函数仍然可以访问。只有通过使用local modname = require "modname",您才能保证准确获取该模块所暴露的内容。

    3. 包含其他模块的模块不能相互干扰。您从require获得的表格始终是模块存储的内容。

  2. 有人过早优化谁读“local变量访问更快”,然后决定让一切local

一般来说,这是很好的做法。那么,除非是因为#2。

+0

3.沉默一个认为调用内置插件这样的linter因为rawset或ipairs是不好的。 – andyn 2015-06-25 10:26:36

0

我这样做,因为它让我看到我的每一个模块

此外,它可以保护你免受他人更改功能在全球环境中使用的功能。 这是一个免费(过早)优化是一个奖金。

+1

没有什么可以阻止您的模块使用不在该列表中的函数。所以如果你突然需要一个全局函数而忘记将它添加到列表中,那么你正在使用全局变量。另外,如果有人改变全局函数,那么他们可能会有这样做的理由,比如监视某些函数的使用等等。 – 2012-02-09 14:16:49

+0

其实有;我有一个预先提交的钩子,它使用luac来搜索GETGLOBAL操作码并发出警告。 – daurnimator 2012-02-09 18:26:33

+0

这是很多工作来实现这么简单的事情。您刚刚使用环境为每个功能提供了特定的全局空间,因此它们不会影响其他人的环境。在Lua书中的编程告诉你所有关于如何做到这一点。 – 2012-02-09 18:40:58

4

除了尼科尔流星锤的答案,我会添加到第3点:

  • 它可以让你的代码从沙盒中它被加载后运行。

如果函数已经从沙箱中排除,并且代码是从沙箱中加载的,那么它将不起作用。但是,如果代码先加载,那么沙箱可以调用加载的代码,并能够从沙箱中排除setmetatable等。

0

另一个微妙的好处是:它清楚地记录了模块导入哪些变量(函数,模块)。如果您使用模块语句,则会强制执行此类声明,因为全局环境会被替换(因此全局变量不可用)。

相关问题