Class Models for Lua

# 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

- Mapping the key `"retrieve"` may lead to unexpected results.
- When using the field `default`, mapping the key `"default"` may lead to unexpected results either.

## 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.