• Subject: Re: Memoizing Functions - yet another attempt
• From: Petite Abeille <petite.abeille@...>
• Date: Sun, 15 Dec 2013 17:59:02 +0100

```On Dec 15, 2013, at 2:34 PM, Sir Pogsalot <sir.pogsalot@gmail.com> wrote:

> On the other hand…

Quagmire or not, here is a little recursive table signer for entertainment purpose.

Usage example:

local foo = Memoize( function( aTable) return aTable, table.unpack( aTable ) end, TableSigner )
local aTable = {  1, 2, 3, 4, 5, 6 }

print( 'foo', 1, foo( { 1, 2, 3 } ) )
print( 'foo', 2, foo( { 1, 2, 3 } ) )
print( 'foo', 3, foo( { a = 1, b = 2, c = 3 } ) )
print( 'foo', 4, foo( { a = 1, b = 2, c = 3 } ) )
print( 'foo', 5, foo( { {}, {}, {} } ) )
print( 'foo', 6, foo( { {}, {}, {} } ) )
print( 'foo', 7, foo( aTable ) )
aTable[ #aTable + 1 ] = aTable
aTable[ #aTable + 1 ] = aTable
aTable[ #aTable + 1 ] = aTable
aTable[ #aTable + 1 ] = true
aTable[ aTable ] = aTable
print( 'foo', 8, foo( aTable ) )
print( 'foo', 9, foo( aTable ) )

Whole hog:

local function Key( aSigner, ... )
local aBuffer = {}

for anIndex = 1, select( '#', ... ) do
aBuffer[ #aBuffer + 1 ] = aSigner( select( anIndex, ... ) )
end

return table.concat( aBuffer )
end

local function Signer( aValue )
return ( tostring( aValue or '' ) or '' ) .. type( aValue ):sub( 1, 2 )
end

local function Memoize( aFunction, aSigner )
local aCache = {}
local aSigner = aSigner or Signer

return function( ... )
local aKey = Key( aSigner, ... )
local aValue = aCache[ aKey ] or table.pack( aFunction( ... ) )

aCache[ aKey ] = aValue

return table.unpack( aValue, 1, aValue.n )
end
end

local function TableSigner( aValue, aSet, aCounter )
local aSet = aSet or {}
local aCounter = aCounter or 0

if type( aValue ) == 'table' and not aSet[ aValue ] then
local aBuffer = {}

aCounter = aCounter + 1
aSet[ aValue ] = ( '%dta' ):format( aCounter )

for aTableKey, aTableValue in pairs( aValue ) do
aBuffer[ #aBuffer + 1 ] = TableSigner( aTableKey, aSet, aCounter ) .. TableSigner( aTableValue, aSet, aCounter )
end

table.sort( aBuffer )
aBuffer[ #aBuffer + 1 ] = 'ta'
aSet[ aValue ] = table.concat( aBuffer )
end

return aSet[ aValue ] or Signer( aValue )
end

```