[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: COW(copy on write) table which contains table element ?
- From: Eike Decker <eike@...>
- Date: Fri, 16 Mar 2007 09:09:05 +0100
This implementation here would be more computational expensive since every table
access is routed through a __index access, but it would map such a table on any
other table. It also will check, if the table key is still valid...
Another problem will be iterating such tables. Pairs and ipairs won't work
anymore - same as next. I would suggest then to overload those functions for
that environment to take these shadowtables into account and traversing them -
as far as possible - correctly. This might be tricky however...
---
local cplist = {}
local function getshadow (tab)
if cplist[tab] then
return cplist[tab] -- don't make multiple copies of the same table
end
local mt = {cpfrom = tab}
local shadow = {}
local cp = {}
setmetatable(shadow,mt)
cplist[tab] = shadow
function mt:__index (key)
local val = cp[key]
if val == nil then
val = tab[key]
if type(val)=="table" then
val = getshadow(val)
cp[key] = val
end
elseif type(val)=="table" and
getmetatable(val).cpfrom~=cp[key] then
cp[key] = nil
return self[key]
end
return val
end
mt.__newindex = cp
return shadow
end
st = { x = 5 , y = {a = 5, b = 4}}
cp = getshadow(st)
print("cp: ", cp.x, cp.y.a, cp.y.b)
print("st: ", st.x, st.y.a, st.y.b)
print "---"
cp.x = 2
cp.y.a = 4
print("cp: ", cp.x, cp.y.a, cp.y.b)
print("st: ", st.x, st.y.a, st.y.b)
print "---"
st.y = {a = 0, b = 0}
st.z = st.y
cp.z.a = 2
print("cp: ", cp.x, cp.y.a, cp.y.b,cp.z.a)
print("st: ", st.x, st.y.a, st.y.b,st.z.a)
print "---"
> gary ng <garyng2000 <at> yahoo.com> writes:
>
> > I am wondering if this is possible. That is I want a
> > table which refers to another table if it doesn't have
> > the particular key and any write does not touch its
> > prototype.
>
> -- Here's one way to do it:
>
> function getShadowTable (t)
> local mt = {}
> function mt:__index (k)
> local v = t[k]
> if type(v) ~= "table" then return v end
> local shadow = getShadowTable(v)
> self[k] = shadow
> return shadow
> end
> return setmetatable({}, mt)
> end
>
> -- It passes your requirements...
>
> t1 = { a = 1, b = {} }
> t2 = getShadowTable(t1)
>
> t1.b.a = 1
> assert(t2.b.a == 1)
> t2.b.a = 2
> assert(t1.b.a == 1)
> assert(t2.b.a == 2)
>
> -- But there are problems if t1.b is replaced after t2.b is read.
> -- That may not arise in your application...
>
> t1 = { a = 1, b = {} }
> t2 = getShadowTable(t1)
>
> t1.b.a = 1
> assert(t2.b.a == 1)
> t1.b = { x = 2 }
> assert(t2.b.x == 2) -- assertion fails
>
>
>
>