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 4:08 am GMT (diff)