Object Cache

loop.collection.ObjectCache


Class of objects that cache values for different key values. Whenever the value of a given a key is requested, a function is used to retrieve the corresponding value that is also cached for further requests of the same key. If the key value is collected as garbage, the cache entry becomes garbage as well. This class is useful for implementing optimizations that avoid re-evaluation of complex operations or duplication of similar objects.

ObjectCache class defines the __index meta-method so that it uses the method retrieve of its instance to retrieve values for keys not already mapped by the instance. If the instance does not provide the method retrieve then it uses the value of field default as the value for keys not mapped. Anyway, the values retrieved for each key are stored in the instance with the corresponding key as index thus further requests for the same key work just like a simple table indexing.

Behavior

Fields

default: any [optional]
Default value used for missing keys. By default this field is nil and may be defined for each instance. This field is only used if no retrieve method is avaliable.

Methods

retrieve(key) [optional]
Method used to retrieve values for a missing key which value is provided by key. By default this field is nil and may be defined for each instance.

Meta-Fields

__index = function
Uses the method retrieve of the instance to retrieve the value requested. Alternatively, it uses the value of field default as the value requested. Anyway, it stores the value obtained in the object with the index provided.
__mode = "k"
Defines that cached keys are weak references thus cached entries are collected if their keys becomes garbage.

Remarks

Examples

Function that prints friendly names for values

local ObjectCache = require "loop.collection.ObjectCache"

local names = ObjectCache()

function names:retrieve(value)
  local type = type(value)
  local id = rawget(self, type) or 0
  self[type] = id + 1
  local label = {}
  repeat
    label[#label + 1] = string.byte("A") + (id % 26)
    id = math.floor(id / 26)
  until id <= 0
  return string.format("%s %s", type, string.char(unpack(label)))
end

function print(...)
  for i=1, select("#", ...) do
    local value = select(i, ...)
    local type = type(value)
    if type == "nil" or type == "boolean" or type == "number" or type == "string" then
      io.write(tostring(value))
    else
      io.write(names[value])
    end
  end
  io.write("\n")
end

for name, value in pairs(_G)        do names[value] = name               end
for name, value in pairs(coroutine) do names[value] = "coroutine."..name end
for name, value in pairs(package)   do names[value] = "package."..name   end
for name, value in pairs(string)    do names[value] = "string."..name    end
for name, value in pairs(table)     do names[value] = "table."..name     end
for name, value in pairs(math)      do names[value] = "math."..name      end
for name, value in pairs(io)        do names[value] = "io."..name        end
for name, value in pairs(os)        do names[value] = "os."..name        end



function f() end

t = { 1, true, {}, f, math.sin, _G }

print("value of f is ",f)
print("value of t is ",t)
for i, value in ipairs(t) do
  print("  value of t[",i,"] is ",t[i])
end

Copyright (C) 2004-2008 Tecgraf, PUC-Rio

This project is currently being maintained by Tecgraf at PUC-Rio.