Lua - Immutable Lists
In Lua, in order to make a list immutable, we can use metamethods and metatables. In this chapter, we'll demonstrate how to make a list immutable.
We'll be using __newindex method, which blocks the entry of new elements to the list.
readOnly function
function readOnly (t)
local proxy = {}
local mt = { -- create metatable
__index = t,
__newindex = function (t,k,v)
error("attempt to update a read-only table", 2)
end
}
setmetatable(proxy, mt)
return proxy
end
readOnly function when applied on any Lua object, makes it immutable. In our scenario, now we can initialize the list in constructor function then pushing an element will be throwing an error as shown in the example below:
Complete Example - immutable Linked List
In below example, we're constructing a list and then making it immutable using readOnly function and then while pushing an element, we're getting error.
main.lua
-- List Implementation
list = {}
list.__index = list
setmetatable(list, { __call = function(_, ...)
local t = setmetatable({ length = 0 }, list)
for _, v in ipairs{...}
do t:push(v)
end
return t
end })
-- push an element to the end of the list
function list:push(t)
-- move till last node
if self.last then
self.last._next = t
t._prev = self.last
self.last = t
else
-- set the node as first node
self.first = t
self.last = t
end
-- increment the length of the list
self.length = self.length + 1
end
-- iterate through the list
local function iterate(self, current)
if not current then
current = self.first
elseif current then
current = current._next
end
return current
end
function list:iterator()
return iterate, self, nil
end
function readOnly (t)
local proxy = {}
local mt = { -- create metatable
__index = t,
__newindex = function (t,k,v)
error("attempt to update a read-only table", 2)
end
}
setmetatable(proxy, mt)
return proxy
end
-- create a new list with values
local l = readOnly(list({1}, {2}, {3}, {4}, {5}))
print("Original List")
-- iterate throgh entries
for v in l:iterator() do
print(v[1])
end
-- try to modify the list
l:push({{7}})
Output
When we run the above code, we will get the following output−
Original List 1 2 3 4 5 lua: main.lua:19: attempt to update a read-only table stack traceback: [C]: in function 'error' main.lua:49: in metamethod 'newindex' main.lua:19: in method 'push' main.lua:66: in main chunk [C]: in ?
Advertisements