lua-users home
lua-l archive

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


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