Read Only Tables

lua-users home
wiki

Showing revision 28
By: KevinBaca

Lua Version: 5.x

Prerequesites: Familiarity with metamethods (see MetamethodsTutorial)

This article describes a technique for making a table readonly. It will prevent the inadvertant modification of any member of a readonly table. Note, however, that members of members of a readonly table can still be modified unless they too are made readonly (see RecursiveReadOnlyTables for an alternative implementation handling recursion).

Suppose we have a table of values that we would like to remain constant.

Directions =
{
    LEFT   = 1,
    RIGHT  = 2,
    UP     = 3,
    DOWN   = 4
}

We can use the metamathods __index and __newindex to ensure that these values never change.

mt =
{
    __index = Directions,

    __newindex = function( table, key, value )
        error( "Attempt to modify read-only table" )
    end
}

Directions = setmetatable( {}, mt )

Now if we try to modify any member of Directions we will get an error.

> Directions.LEFT = 33
Attempt to modify read-only table

Note that, as mentioned above, members of members of readonly tables can still be modified. For example:

Directions =
{
    LEFT   = 1,
    RIGHT  = 2,
    UP     = 3,
    DOWN   = 4,

    otherstuff =
    {
    }
}

The table Directions.otherstuff cannot be changed or removed, but its contents can be changed or removed:

> Directions.otherstuff = nil    -- will fail
Attempt to modify read-only table
> Directions.otherstuff.foo = 1  -- OK

Note also that rawset() can still be used to modify a readonly table, and that access to setmetatable() will allow the user to change this behaviour. Furthermore table.insert, etc. will also directly modify the table.

Note, however, that this construct interferes with pairs, ipairs, next, the # operator, and other forms of table iteration. For example,

-- prints nothing!
for k,v in pairs(Directions) do
  print(k,v)
end

-- prints nil!
print(next(Directions))

-- prints "0"!
print(#Directions)

See also GeneralizedPairsAndIpairs for ways to handle that.


RecentChanges · preferences
edit · history · current revision
Edited February 13, 2007 11:02 pm GMT (diff)