Objective
Lua saves all of its global variables in a regular table, which is called the "environment." The advantage of this organizational structure is that one does not need to create a new data structure for global variables, thus simplifying the internal implementation of LUA; Another advantage is that you can manipulate the table like any other table. To facilitate this operation, LUA saves the environment table itself in a global variable _g. For example, we can use the following code to print the names of all global variables in the current environment.
Copy Code code as follows:
For n in pairs (_g) does print (n) end
Run the above code on your computer to see the results.
global variable Declaration
In Lua, global variables can be used directly without a declaration, but this violates the taboo of programming, using global variables, which will result in the performance of the program, when there are bugs, it is difficult to find, but also contaminated the program naming. Considering that the global variable is also stored in a table, we can change the behavior of other code accessing the global variable through the meta table, see? Again the meta table. The code is as follows:
Copy Code code as follows:
Setmetatable (_g, {
__newindex = function (_, k)
Error ("Attempt to write to undeclared variable".) K
End
__index = function (_, k)
Error ("Attempt to read undeclared variable".) K
End
})
Print (a)--here A is a global variable
And sometimes, we really need to define a global variable, so what? Remember what I wrote in the "Wenzu and meta method" in the LUA article? Using Rawset can be done, it is different over the table, directly set the value of the table, at the same time, in order to test the existence of a variable, you can not simply compare it with the nil. Because if it's nil, the access throws an error, and again, we can use Rawget to circumvent the meta method.
Variables that are not global
Since the concept of "environment" is global, any modification to him will affect all parts of the program. For example, if you install a meta table to control access to global variables, the entire program must follow this specification. But when you use a library, you use a global variable without first declaring it, and then the program cannot run.
You can change the environment of a function by setfenv the function. The function's argument is a function and a new environment table. The first parameter can be specified as a number, in addition to the function itself, to represent the number of layers in the current function call stack. The number 1 represents the current function, and the number 2 represents the function that called the current function, and so on. Let's start with a little piece of code:
Copy Code code as follows:
A = 1--A global variable is created here
--Change the current environment variable to a new empty table
Setfenv (1, {})
Print (a)
Running code will pop up the error: Attempt to call global ' print ' (a nil value)
Print is stored in _g, because we have reset the current environment variable to an empty table, resulting in the failure to find the print, so there is an error. To prevent such a false release, we need to save the current environment variable before we change the current environment variable. Look at the following code:
Copy Code code as follows:
A = 1--A global variable is created here
--Change the current environment variable to a new empty table
Setfenv (1, {g = _g})
G.print (a)--output nil
G.print (G.A)--Output 1
This time access to G will get the original environment, this environment contains the field print. We can use the name _g instead of G, as shown in the following code:
Copy Code code as follows:
A = 1--A global variable is created here
--Change the current environment variable to a new empty table
Setfenv (1, {_g = _g})
_g.print (a)--output nil
_g.print (_G.A)--Output 1
Don't forget the __index meta method we summed up before, we can set the __index of the new environment variable to _g, so that when the corresponding variable is not found in the new environment, it will go to the _g, so that the new environment variable inherits the Global environment variable _g, look at the following code:
Copy Code code as follows:
A = 1--A global variable is created here
Local newenv = {}
Setmetatable (newenv, {__index = _g})
--Change the current environment variable to a new empty table
Setfenv (1, newenv)
Print (a)
In Lua, a function inherits the environment in which it is created, so if a block changes its own environment, subsequent functions created by it will share the new environment. This mechanism is useful for creating namespaces. Later in the summary will continue to explain.