CONST
After reading a for a long while and reviewing other people's code on the subject of read-only tables, I've hacked together some code (thanks to the interweb's numerous forums and the lua manual) that let's you define and use constants.
This is my first run, thought I'd post it in case anyone else has a need for it.
EDIT: Updated code to a new version.
(0.3.0.0)
Usage Example
These constants cannot be overwritten (by normal means).
After reading a for a long while and reviewing other people's code on the subject of read-only tables, I've hacked together some code (thanks to the interweb's numerous forums and the lua manual) that let's you define and use constants.
This is my first run, thought I'd post it in case anyone else has a need for it.
EDIT: Updated code to a new version.
(0.3.0.0)
Code:
local tConst = { AllowedValueTypes = {"boolean", "number", "string"}, ThrowErrorsByDefault = true, --this can be changed individually for each CONST type created using :SetThrowErrors(boolean); Types = {}, } --determines whether or not this CONST type will throw errors local function GetThrowErrors(sName) local bRet = false; if (tConst.Types[sName]) then bRet = tConst.Types[sName].ThrowErrors; end return bRet; end --determines whether or not the sumbitted type is an allowed CONST value type local function IsAllowedValueType(sValueType) local bRet = false; for _, sAllowedValueType in pairs(tConst.AllowedValueTypes) do if (sValueType == sAllowedValueType) then bRet = true; break; end end return bRet; end function tConst.Create(sName) --make sure the input is good assert(type(sName) == "string" and sName:gsub("%s", "") ~= "", "Error creating CONST type. Input must be a non-blank string."); local tReturnTable = {}; --ensure the CONST type doesn't already exist if (not tConst.Types[sName]) then --create the CONST shadow table local tShadow = {}; --store the CONST type name and set the default error flag tConst.Types[sName] = {ThrowErrors=tConst.ThrowErrorsByDefault}; --============================================ -- Begin Metamethods --=========================================== --========== -- NewIndex --========== --this is called whenever a new index is created within the new CONST type table local function NewIndex(tTable, nKey, nValue) local sType = type(nValue); --make sure the CONST has not already been defined if (tShadow[nKey]) then if (GetThrowErrors(sName)) then error('"'..sName..'.'..nKey.. '" has already been defined with value "'.. tostring(tShadow[nKey])..'" and is of type "'.. type(tShadow[nKey])..'".'); end else --make sure the CONST is of the correct type if (IsAllowedValueType(sType)) then tShadow[nKey] = nValue; else --throw an error (if errors are on) if (GetThrowErrors(sName)) then error('A "'..sName.. '" may be of type "boolean", "number" or "string" only. Input was of type "'.. sType..'".'); end end end end --========= -- GetAll --========= local function GetAll() local tRet = {}; for k, v in pairs(tShadow) do local sVType = type(v); if (type(k) == "string" and IsAllowedValueType(sVType)) then tRet[k] = v; end end return tRet; end --============================================ -- End Metamethods -- -- Begin CONST type exposed functions --============================================ --this is the table whose metatable is set and is used to set functions local tConstType = {}; --================ -- SetThrowErrors --================ function tConstType.SetThrowErrors(bValue) local sType = type(bValue); local bFlag = bValue; if (sType ~= "boolean") then bFlag = false; end tConst.Types[sName].ThrowErrors = bFlag; end --adjust the metatable of the new tConstType and return that value tReturnTable = setmetatable(tConstType, { __call = GetAll, __index = tShadow, --the shadow reference __newindex = NewIndex, __type = sName, }); else tReturnTable = _G[sName]; if (GetThrowErrors(sName)) then error("Error creating CONST type. CONST type already exists."); end end return tReturnTable; end CONST = tConst.Create;
Usage Example
Code:
RESOURCE = CONST("RESOURCE"); RESOURCE.AMMO = "Ammo"; RESOURCE.FUEL = "Fuel"; RESOURCE.FUEL_BASE_COST = 25; RESOURCE.IS_FREE = false; --RESOURCE.SetThrowError(false);--uncomment to ignore errors for this CONST type RESOURCE.AMMO = "stuff"; --throws an error, already set (even if errors are ignored, the value cannot be changed)
These constants cannot be overwritten (by normal means).
Comment