Simple Tuples

lua-users home
wiki

A very simple interned immutable 2-tuple implementation. Tuple members cannot be nil or NaN:

-- An interned 2-tuple type, in pure Lua.
--
do
  -- The constructor makes a tuple function, which has its own
  -- intern table.
        
  local setmetatable = setmetatable

  local function tmaker(a)
    return {__index = function(t, b)
                        local function tuple() return a, b end
                        t[b] = tuple
                        return tuple
                      end,
            __mode = "kv"
           }
  end 
  local meta = {
      __index = function(t, a)
                  local v = setmetatable({}, tmaker(a))
                  t[a] = v
                  return v
                end,
      __mode = "k"
  } 
  return function()
    local intern = setmetatable({}, meta)
    return function(a, b)
      return intern[a][b]
    end
  end
end

The __mode lines are optional; in practice, I use this with tuple-caches which are not long-lived, and it is easier to throw away the entire cache.

Usage: Put the above in a file named, for example, TupleCache.lua. Create a tuple function:

local FooTuple = require"TupleCache"()

Then you can create new FooTuples using the tuple function:

local t = FooTuple(obja, objb)

The FooTuple function itself has the only reference to the cache tables, so the cache tables will be garbage collected once FooTuple no longer has references. However, the tuples themselves will continue to exist; you simply cannot make new ones.

To extract the values of a tuple, call it:

local obja, objb = t()

If you really need tuples capable of containing nil and NaN, you can use this version:

do
  -- The constructor makes a tuple function, which has its own
  -- intern table.

  local rawget, setmetatable = rawget, setmetatable
  local NIL, NAN = {}, {}
  
  local function check(t, a)
    if a == a and a ~= nil then return a end
    local fixa = a and NAN or NIL
    return fixa, rawget(t, fixa)
  end

  local function tmaker(a)
    return {__index = function(t, b)
                        local fixb, tuple = check(t, b)
                        tuple = tuple or function() return a, b end
                        t[fixb] = tuple
                        return tuple
                      end
           }
  end
  local meta = {
      __index = function(t, a)
                  local fixa, v = check(t, a)
                  v = v or setmetatable({}, tmaker(a))
                  t[fixa] = v
                  return v
                end
  }
  return function()
    local intern = setmetatable({}, meta)
    return function(a, b)
      return intern[a][b]
    end
  end
end

See Also


RecentChanges · preferences
edit · history
Last edited August 3, 2007 5:08 am GMT (diff)