Read Only Tables

Problem Definition

Construct a table that is read only. Users will not be allow to add new indices

Problem Solution Discussion

A read only table can be constructed using a proxy<br>

   1\. The proxy table will be empty
   2\. The __index metamethod will be assigned the original table.
      This will cause accesses (reads) to be looked up in the table
      that is in __index (this is the definition of __index it is either
      a function or a table)
   3\. The __newindex metamethod will be a function that returns an error
      This will cause a updates (writes) to be rejected.  Since the proxy
      table is empty __newindex will be called for each write to the table
      and an error will be returned.
```

_**Solution**_

The code of the module for the read only proxy is the following

```

--[[Take a table and make a proxy for that table that will be empty and
    therefore call the __index and __newindex metamethods for every access.
    The _newindex metamethod will return an error so that no new indices can
    be made in the table.  The _index method will look up the value in the
    table which has been assign to the __index metamethod]]
function readOnly (t)
  local proxy = {}
  local mt = {
    __index = t,
    __newindex = function(table, key, value)
      print("attempt to update a read-only table, operation " .. key .. " = " .. value .. " not performed")
    end
  }
  setmetatable(proxy, mt)
  return proxy
end
```

The code that exercises the module is the following

```

--[[This is the code to exercise the metatableReadOnly.metatableProxyModule code]]

require "metatableReadOnly.metatableProxyModule"
local days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
days = readOnly(days)
print(days[1])
days[2] = "None"

local planets = {planet1="Mercury", planet2="Venus", planet3="Earth", 
                            planet4="Mars", planet5="Jupiter", planet6="Saturn", planet7="Uranus", planet8="Neptune"}
planets = readOnly(planets)

print(planets.planet8)
planets.planet8 = "Xergon"
```