How special is the global variable _G?
How special is the global variable _G
?
It is special in three ways:
- It uses a name reserved for internal use by Lua.
- It is create by one of Lua's standard modules (in particular the
"base" module). If you create a fresh
lua_State
without opening the "base" module, you won't have the_G
variable. The standalone interpreter has all standard libraries already loaded, though. - Some third-party Lua modules use the global variable
_G
, and changing/removing it can break those modules.
What's the point of _G
?
Global variables in Lua are implemented using a normal table. Any
access to a variable that is not a local
variable or an upvalue will
be redirected to this table. Local variables always take priority, so
if you have a global variable and a local variable with the same name,
you will always get the local one. And here _G
comes into play: If
you want the global variable, you can say _G.name
instead of name
.
Assuming the name _G
is not a local variable (it's reserved for Lua,
remember?!), this will always get you the value of the global variable
by using table indexing syntax and thus removing the ambiguity with
local variable names. In newer Lua versions (5.2+) you could also use
_ENV.name
as an alternative, but _G
predates those versions and is
kept for compatibility.
There are other cases where you want to get a hold of the globals
table, e.g. for setting a metatable. Lua allows you to customize the
behavior of tables (and other values) by setting a metatable using the
setmetatable
function, but you have to pass the table as a
parameter somehow. _G
helps you do that.
If you have added a metatable to the globals table, in certain cases
you might want to circumvent the metamethods (__index
and/or
__newindex
) you've just installed. You can use rawget
and
rawset
, but you need to pass the globals table as a parameter
as well.
Note that all the use-cases listed above only apply to Lua code not
C code. In C code you don't have named local variables, only stack
indices. So there is no ambiguity. And if you want a reference of the
globals table to pass to some function, you can use
lua_pushglobaltable
(which uses the registry instead of _G
).
As a consequence, modules implemented in C don't use/need the _G
global variable. This applies to Lua's standard library (which is
implemented in C) as well. In fact, the references manual
guarantees, that _G
(the variable, not the table) is not used
by Lua or its standard library.
How does _G
relate to _ENV
?
Since version 5.0 Lua allows you to change the table used to look up
global variables on a per-(Lua-)function basis. In Lua 5.0 and 5.1
you used the setfenv
function for that (the globals table is
also called "function environment", hence the name setfenv
). Lua 5.2
introduced a new approach using another special variable name _ENV
.
_ENV
is not a global variable though, Lua makes sure that every
chunk starts with an _ENV
upvalue. The new approach works by letting
Lua translate any access to a non-local (and non-upvalue) variable
name a
to _ENV.a
. Whatever _ENV
is at that point in the code
gets used to resolve global variables. This way is a lot safer because
you can't change the environment of code you didn't write yourself
(without using the debug library), and also more flexible because you
can change the environment for individual blocks of code by creating
local
_ENV
variables with limited scopes.
However, in any case you need a default environment that is used
before the programmer has a chance to set a custom one (or if the programmer
does not want to change it). On startup, Lua creates this default
environment (also called "global environment") for you and stores
it in the registry. This default environment is used as the
_ENV
upvalue for all chunks unless you pass custom environments to
load
or loadfile
. lua_pushglobaltable
also
retrieves this global environment directly from the registry, so
all C modules automatically use it for accessing global variables.
And if the standard "base" C module has been loaded, this
default "global environment" has a table field called _G
that refers
back to the global environment.
To sum it up:
- The global variable
_G
is actually_ENV._G
. _ENV
is not a global, but an upvalue or a local variable.- The
_G
field of the default "global environment" points back to the global environment. _G
and_ENV
by default refer to the same table (said global environment).- C code doesn't use either, but a field in the registry (which again points to the global environment by definition).
- You can replace
_G
(in the global environment) without breaking C modules or Lua itself (but you might break third-party Lua modules if not careful). - You can replace
_ENV
whenever you want, because it only affects your own code (the current chunk/file at most). - If you replace
_ENV
, you can decide for yourself whether_G
(_ENV._G
) will be available in the affected code, and what it points to.