12

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?

Ensemble
  • 230
  • 2
  • 7
  • 1
    You may want to have a look at http://stackoverflow.com/questions/4643814/why-would-this-lua-optimization-hack-help – Michal Kottman Feb 08 '12 at 22:29
  • For variables: [Why are local variables accessed faster than global variables in lua? - Stack Overflow](https://stackoverflow.com/questions/9132288/why-are-local-variables-accessed-faster-than-global-variables-in-lua) – user202729 Jun 27 '22 at 06:27

4 Answers4

13

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:

  1. 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:

    1. One module cannot accidentally overwrite another module's functions.

    2. 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.

    3. Modules that include other modules can't interfere with one another. The table you get back from require is always what the module stores.

  2. A premature optimization by someone who read "local variables are accessed faster" and then decided to make everything local.

In general, this is good practice. Well, unless it's because of #2.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 3. Silencing a linter which thinks that calling built-ins such as rawset or ipairs is bad. – andyn Jun 25 '15 at 10:26
5

In addition to Nicol Bolas's answer, I'd add on to the 3rd point:

  • It allows your code to be run from within a sandbox after it's been loaded.

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.

BMitch
  • 231,797
  • 42
  • 475
  • 450
1

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.

daurnimator
  • 4,091
  • 18
  • 34
  • 2
    There's nothing to prevent your module from using functions that aren't on that list. So if you have a sudden need for a global function and forget to add it to the list, then you're using globals. Also, if someone changes the global functions, then there's probably a *good* reason for them to do so, such as monitoring the use of certain functions and so forth. – Nicol Bolas Feb 09 '12 at 14:16
  • 1
    Actually there is; I have a pre-commit hook that uses luac to search for GETGLOBAL opcodes and warn me. – daurnimator Feb 09 '12 at 18:26
  • 1
    That's a lot of work to implement something so simple. You have just used environments to provide a specific global space to each function, so they couldn't affect someone else's. The Programming in Lua book tells you all about how to do this. – Nicol Bolas Feb 09 '12 at 18:40
  • 1
    It's best to never use globals; particulary in large programs or when writing libraries; even when constrained into an environment. By checking for GETGLOBAL I also often find typos and code missed in refactoring; overall its a much nicer way to code. – daurnimator Feb 09 '12 at 20:06
  • 1
    Again, protection from globals can be done by setting the appropriate environment. Parsing though compiled source code for some particular opcode is much more difficult than just setting the environment up correctly. Plus, you don't have to stick a giant preamble into all of your scripts. – Nicol Bolas Feb 09 '12 at 20:10
  • The point is that I LIKE the preamble; it allows me to see what functions I use in each file at a glance – daurnimator Feb 09 '12 at 20:14
0

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).

mlepage
  • 2,372
  • 2
  • 19
  • 15