Automagic Tables

lua-users home
wiki

Building on some of the techniques illustrated in FuncTables, here are some implementations of Perl-style[1] automagic tables (also called autovivication). An automagic table creates subtables on demand, as it were; i.e.:

a = AutomagicTable()
a.b.c.d = "a.b and a.b.c are automatically created"

This version was the result of several interesting interchanges between ThomasWrensch and me (RiciLake), and I cannot take credit for it (although I am happy to take the blame; I've made a couple of modifications and changed the formating because I like spaces in parameter lists)

do
  local auto, assign

  function auto(tab, key)
    return setmetatable({}, {
            __index = auto,
            __newindex = assign,
            parent = tab,
            key = key
    })
  end

  local meta = {__index = auto}

  -- The if statement below prevents the table from being
  -- created if the value assigned is nil. This is, I think,
  -- technically correct but it might be desirable to use
  -- assignment to nil to force a table into existence.

  function assign(tab, key, val)
  -- if val ~= nil then
    local oldmt = getmetatable(tab)
    oldmt.parent[oldmt.key] = tab
    setmetatable(tab, meta)
    tab[key] = val
  -- end
  end

  function AutomagicTable()
    return setmetatable({}, meta)
  end
end

[*] There is a Lua 4 version of this as well, but it is not as tidy.


A comment made by ThomasWrensch seemed relevant, I quote it without permission so I hope he doesn't mind:

I think the technique above -- the use of an individualized metatable with additional non-metamethod keys -- is more than just a handy trick.

If you want to associate some information with a table you have three choices:

1. Put a key in the table with the information
2. Use the table as a key in another (possibly weak) table.
3. Associate it with the metatable.

The problem with the first trick is it may conflict with an existing key and/or pollute the table with inappropriate data. You pointed out some of the problems with the second approach in your message (on GarbageCollectingWeakTables) a while ago. The third requires the use of an individual metatable, but does not have the problems of the other two techniques.

-- ThomasWrensch


FindPage · RecentChanges · preferences
edit · history
Last edited January 20, 2007 4:08 am GMT (diff)