Comparison By Value

lua-users home
wiki

The function hashed below adds a metatable to the given table t, so that any write or read in the table will actually use a hash of the key instead of the key itself. This allows simulating the comparison of keys by values. To achieve that, make sure that two objects (table or userdata) that should have the same value have the same hash.

local function gethash(k)

  local hash = k

  local mt = getmetatable(k)

  local __hash = mt and mt.__hash

  if type(__hash)=='function' then

    hash = __hash(k)

  elseif type(__hash)~='nil' then

    hash = __hash

  end

  return hash

end



function hashed(t)

  return setmetatable(t, {

    __index = function(t, k)

      return t[gethash(k)]

    end,

    __newindex = function(t, k, v)

      rawset(t, gethash(k), v)

    end,

  })

end



-- example usage



local t1 = setmetatable({}, {__hash = 42})

local t2 = setmetatable({}, {__hash = 42})



local t = {}

t[t1] = "foo"

assert(t[t2]==nil)



t = hashed({})

t[t1] = "foo"

assert(t[t2]=="foo")

t[t2] = "bar"

assert(t[t1]=="bar")

Here's an alternate implementation --DavidManura

local mt = {

  __mode = 'kv',

  __index = function(t,k) return k end

}

local function newkeymap(t) return setmetatable(t or {}, mt) end



function hashed(t, keymap)

  return setmetatable(t, {

    __index    = function(t, k) return rawget(t, keymap[k]) end,

    __newindex = function(t, k, v) rawset(t, keymap[k], v) end,

  })

end



-- example usage



local t = {}

t.BAR = "foo"

assert(t.bar==nil)



local keymap = newkeymap { BAR = 'bar' }

t = hashed({}, keymap)

t.bar = "foo"

assert(t.BAR=="foo")

t.BAR = "bar"

assert(t.bar=="bar")


RecentChanges · preferences
edit · history
Last edited September 5, 2008 1:22 am GMT (diff)