Is there a way to know if there is a key added or removed from an array in lua?

349 Views Asked by At
local t = {}
local mt = setmetatable({
        -- some meta method to know when a key is added or lost and prints a message
      }, t)

Is there a way of doing this. I talked about this with someone and they said i couldn't just do it with meta methods but proxies as well. I'm a bit stumped on how to make this work. Can anyone help?

Thanks

2

There are 2 best solutions below

1
Darius On BEST ANSWER

To track table keys in lua there are 2 most importaint keys in metatable: __index and __newindex.

__newindex is used to create new key in the table if such key is not found. __index is used to get the value if there is no such key in table.

With __newindex it is possible to track creation, but not assignment, so it is not possible to track key removal:

<script src="https://github.com/fengari-lua/fengari-web/releases/download/v0.1.4/fengari-web.js"></script>
<script type="application/lua">

local t={}
setmetatable(t, {
  __newindex = function(self, key, value)
    print('Added Key:'..key,'Value:'..value)
    rawset(self, key, value)
  end
})

t.test = 'test'
t.test = nil -- delete not tracked
t.test = 'test2'

</script>

Using proxy table and __newindex with __index we can track every assignment:

<script src="https://github.com/fengari-lua/fengari-web/releases/download/v0.1.4/fengari-web.js"></script>
<script type="application/lua">

local t={}
local proxytable={}
setmetatable(t, {
  __newindex = function(self, key, value)
    if proxytable[key] then
      if value == nil then
        print('Deleted Key:'..key)
      else
        print('Changed Key:'..key,'Value:'..value)
      end
    else
      print('Added Key:'..key,'Value:'..value)
    end
    rawset(proxytable, key, value)
  end,
  __index = proxytable
})

t.test = 'test'
t.test = nil
t.test = 'test2'
t.test = 'test3'
t.test = nil

</script>

If you want enumerate table keys with pairs(), ipairs(), then you need to use metakeys __pairs and __ipairs as original table is allways empty.

2
Doyousketch2 On
local tab = {}
local meta = {}

setmetatable( tab,
    {  __newindex = function( self, key, value )
          print( key, value )
          rawset( self,  key,  value  )
       end
    } )

tab [1] = 'this'
tab [#tab +1] = 'that'
tab .the = 'other'
tab [3] = nil
tab [4] = 2