lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

For Lua-based objects note that you can add essentially arbitrary keys to the object. You can even keep these moderately private by using tables rather than strings as keys. The "moderate" part stems from the fact that you can discover them via iteration. In fact, as long as the objects aren't used with the pairs iterator (or next), it should generally be safe to add the extra fields.

For userdata, you would need to add support for storing arbitrary references presumably using the environment table.

But the key point is that so long as the objects don't need to be iterable, it actually isn't all that hard to store extra links into them.



-- WARNING: Untested. Not even compiled.

local kLevel1Key = { }
local kLevel2Key = { }

-- cacheRoot auto constructs the succeeding levels

-- Base tables will simply be fully weak

local kFullyWeak = { __mode = 'kv' }

local function makeBase()
	return setmetatable( {}, kFullyWeak )

-- Given a constructor function, we want an __index function that runs the constructor and
-- stores the result.

local function makeConstructingIndex( constructor )
	return function( t, k )
		local v = constructor()
		t[ k ] = v
		return v

-- Given a constructor function, we want a metatable for tables that auto-populate.

local function makeConstructingMetatable( constructor )
	return { __mode = 'kv', _index = makeConstructingIndex( constructor ) }

-- Given the constructor for the next level in the cache, create a constructor for this level.

local function makeConstructor( nextLevelConstructor )
	local mt = makeConstructingMetatable( nextLevelConstructor )
	return function()
		return setmetatable( {}, mt )

-- For a three level cache, we do one round of wrapping

local cacheRoot = setmetatable( { },
	makeConstructingMetatable(	-- Constructs first level
		makeConstructor(		-- Constructs second level
			makeBase ) ) )		-- Constructs leaves

function storeCachedObject( object, key1, key )

	local t1 = cacheRoot[ key1 ]
	local t2 = t1[ key2 ]

	t2[ key3 ] = object
	object[ kLevel1Key ] = t1
	object[ kLevel2Key ] = t2

	return object

-- BONUS POINTS: The cache could actually auto construct the object but then it needs to have back links to -- find the path through the cache. This could be done using private links in the cache tables. If doing that, -- we might try to arrange for a strong back chain via an extra level of indirection in the cache tables. Logic
-- to do so not evaluated here.