1
votes

I have this code, but I don't want the tbl variable getting width and height assigned to it, rather I want base_table's width and height properties getting modified to 200 rather than tbl getting assigned a height and width of 200.

function deepCopy(original)
    local copy = {}
    for k, v in pairs(original) do
        if type(v) == "table" then
            v = deepCopy(v)
        end
        copy[k] = v
    end
    return copy
end

function PrintTable(t)
    for k, v in pairs(t) do
        if v == "table" then
            PrintTable(v)
        else
            print(k, v)
        end
    end
end

local base_table = {
  width = 0,
  height = 0,
  x = 0,
  y = 0,

  SetSize = function(self, w, h)
    self.width, self.height = w, h
  end,

  SetPos = function(self, x, y)
    self.x, self.y = x,y
  end

}

local tbl = {}

local meta = {__index = deepCopy(base_table)}

setmetatable(tbl, meta)


PrintTable(tbl) -- prints nothing

tbl:SetSize(200, 200)

PrintTable(tbl) -- prints height 200, width 200 which I don't want, I want it to print nothing like above. though if I do tbl.x I want it to 200, since it would be on the metatable, rather than the tbl itself 
1
Replace local meta = {__index = deepCopy(base_table)} with local cpy = deepCopy(base_table); local meta = {__index = cpy; __newindex = cpy}Egor Skriptunoff
Thanks once again @EgorSkriptunoff post your solution as an answer and i'll acceptnoobyy
But with my solution all properties goes to metatable, not only width and height. PrintTable(tbl) will always be empty.Egor Skriptunoff
I see, what you mean after testing it and reading __newindex documentation. that's problematic for me. I still want to be able to define stuff on tbl. I want, when I invoke a metatable function, and the metatable function modifies a property that is defined on the metatable, it will modify the metatable property instead of creating a new property on the tblnoobyy
Maybe it's possible to get what I want using the __newindex metamethod if there isn't a straight forward solution. I will play around with it.noobyy

1 Answers

1
votes
local function deepCopy(original)
   local copy = {}
   for k, v in pairs(original) do
      if type(v) == "table" then
         v = deepCopy(v)
      end
      copy[k] = v
   end
   return copy
end

local function PrintTable(t)
   for k, v in pairs(t) do
      if v == "table" then
         PrintTable(v)
      else
         print(k, v)
      end
   end
end

local base_table = {
   width = 0,
   height = 0,
   x = 0,
   y = 0,

   SetSize = function(self, w, h)
      self.width, self.height = w, h
   end,

   SetPos = function(self, x, y)
      self.x, self.y = x,y
   end

}

local tbl = {}
local cpy = deepCopy(base_table)
setmetatable(cpy, {__newindex = function(_, k, v) rawset(tbl, k, v) end})
setmetatable(tbl, {__index = cpy; __newindex = cpy})

PrintTable(tbl) -- prints nothing

tbl:SetSize(200, 200)
tbl.someproperty = "some value"

PrintTable(tbl) -- prints only someproperty