Simple Tuples |
|
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