Lua Constants

Posted by Terry on Sun 15 Jul 2007 10:34 AM — 5 posts, 35,509 views.

USA #0
How do you do Lua's equivalent to C's #define? When I looked through Lua's documentation, I found a lot about metatables, but I really didn't understand any of it :( Would someone be willing to help me out?
USA #1
You can just make a variable to hold pretty much anything. I'd need a specific example of what you're doing, but I frequently do things like define os.time() and os.difftime() in plugins to compensate for the fact that some people might have those permissions turned off. From the Lua users wiki:
> x = function(a,b) return a+b, a-b end
> = x(5,6)
11      -1
> function x(a,b,c) return a..b..c end
> = x('a','b','c')
abc

USA #2
Forgot to mention, Lua is quite forgiving with where you put variables. You can replace just about anything just about anywhere. Makes it so you have to pay a bit more attention to what you're doing, since errors aren't always thrown when you do something you didn't want to, but it makes life a little easier along the way. A #define is really just a constant anyway.
USA #3
To define a "constant", you can just stick a variable at the top of a Lua script and give it a value, like

MY_CONSTANT = 2

Of course, it's not really a constant because you can change it; if you want it to be a proper constant you have a little more work to do.
Australia Forum Administrator #4
If you set your mind to it, you can make constants by putting them in a table, and with metatables make it so you can't change it.

This example demonstrates that:



function protect_table (tbl)
  return setmetatable ({}, 
    {
    __index = tbl,  -- read access gets original table item
    __newindex = function (t, n, v)
       error ("attempting to change constant " .. 
             tostring (n) .. " to " .. tostring (v), 2)
      end -- __newindex 
    })

end -- function protect_table


-------------------------- test -----------------

my_constants =
  {
  WIDTH = 22,
  HEIGHT = 44,
  FOO = "bar",
  }

-- protect my table now
my_constants = protect_table (my_constants)

-- test it
print ("WIDTH",  my_constants.WIDTH)  --> WIDTH 22
print ("HEIGHT", my_constants.HEIGHT) --> HEIGHT 44

my_constants.WIDTH = 44  --> Error: attempting to change constant WIDTH to 44


The function 'protect_table' makes a copy of the original table, and returns an empty one, with a metatable attached to it. The metatable allows read access (via __index) but stops write access (via __newindex).