Explicit variables

The loose, typed nature of variables in Lua can be great for prototyping games quickly, but it can also lead to a lot of bugs! For example, consider the following code:

five21 = 521 -- Variable name ends with a 1

for i=1,1000 do
if i == five21 then
five2l = "Five Twenty One" -- ERROR! Variable name ends with an l
break
end
end

print("value: " .. five21)

Can you spot the problem? During the first assignment, the five21 variable ends with a 1, but in the second assignment it ends with a lower case l. Characters such as 0 and O, 1 and l, or I and l can lead to easy typos depending on the font being used.

You can fix these types of typos using explicit variable declaration. Set the __newindex and __index metamethods of the global table to track whether a variable being used has been declared or not. This implies that you will need to create a function to declare variables, and a table to track all declared variables.

This is a bit unintuitive, but it's another example of how powerful Lua is. First, create the table that will store a list of variables that have been declared, and set the meta table for _G:

_G.declared = {}
setmetatable(_G, _G)

Next, create the Declare function. This will simply set a flag in the declared table to true:

_G.Declare = function(k, v) 
_G.declared[k] = true
end

The __index metamethod of _G should only return values if the key being retrieved is present in the declared table. Here, use rawget to avoid a recursive call:

_G.__index = function(t, k)
if not _G.declared[k] then
print ("Can't read undeclared variable: " .. k)
return nil
end
return rawget(t, k)
end

Similarly, the __newindex metamethod must first check whether a variable has been declared. If so, this function uses rawset to add the new key to the global table:

_G.__newindex = function(t, k, v) 
if not _G.declared[k] then
print ("Can't write undeclared variable: " .. k)
else
rawset(t, k, v)
end
end

The following code demonstrates how to use the preceding changes in the global table:

Declare("x") -- Declare in _G
Declare("y") -- Declare in _G

x = 21
y = 22

print (x .. ", " .. y)

z = 5 -- Can't add to _G if not declared
print (z)

local w = 19 -- Local to the file, not in _G
print ("w: " .. w)

The preceding code declares variables x and y, putting both keys into the declared table. Next, it assigns values to the variables that invoked the _newindex metamethod. Because the variables have been declared, they are allowed to be set, otherwise an error would occur. After that, the print statement invokes the __index metamethod, which retrieves the variables.

When a value is assigned to z, the __newindex metamethod sees that this variable was not declared and prints a warning. Because the variable is not declared, trying to print the value of z also results in an expected error. The w variable is created local to the current Lua file; it will not be recorded in the global table _G.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.7.131