The fare-memoization Reference Manual

Table of Contents

Next: , Previous: , Up: (dir)   [Contents][Index]

The fare-memoization Reference Manual

This is the fare-memoization Reference Manual, version 1.2.0, generated automatically by Declt version 2.4 "Will Decker" on Wed Jun 20 11:45:29 2018 GMT+0.


Next: , Previous: , Up: Top   [Contents][Index]

1 Introduction

FARE-MEMOIZATION

This library builds on an age-old idea: dynamically memoizing Lisp functions.
A memoized function remembers results from previous computations, and
returns cached results when called with the same arguments again,
rather than re-do the computation. This library allows you
to focus on the computation logic and handles the caching part for you.
It also allows you to memoize a function after the fact when you need it.
Obviously, you should only use memoization for functions where it is meaningful:
pure functions that are expensive to compute,
non-deterministic functions for which it matters that choices be consistent,
hash-consing constructors that need return the same result when called with
the same arguments, user-visible constructors for singleton classes, etc.

This file first documents the interface of this library, then
compares fare-memoization to previous memoization libraries,
and finally discusses a false good idea of feature I had.


==== Exported Functionality ====

The fare-memoization library creates a package FARE-MEMOIZATION,
with nickname FMEMO, that exports the following macros and functions:

MEMOIZE SYMBOL &KEY TABLE NORMALIZATION
  This function memoizes the function associated to given SYMBOL.
  If the function was already memoized, it resets
  the associated memoization TABLE and NORMALIZATION function
  to those explicitly specified by this latter call to MEMOIZE, or
  to their implicit defaults (respectively a fresh EQUAL hash-table and NIL).
  Beware that function was declared NOTINLINE, callers are not guaranteed
  to see the memoized function rather than have inlined the original one.
  Moreover, if the function is self-recursive, this
  (declaim (notinline SYMBOL)) must have happened before it was defined.
  Keyword arguments TABLE and NORMALIZATION are as usual (see below).

UNMEMOIZE SYMBOL
  This function undoes what MEMOIZE did to the given SYMBOL.

UNMEMOIZE-1 SYMBOL &REST ARGUMENTS
  This function removes one entry from the memoization cache of SYMBOL.
  It returns T if an entry was found and removed corresponding to ARGUMENTS,
  and NIL if none was found.

DEFINE-MEMO-FUNCTION NAME FORMALS &BODY BODY
  This macro is like DEFUN, but its the defined function will be memoized.
  If NAME is a CONS rather than a symbol,
  the actual name for DEFUN will be its first element, and
  the rest will be a list with keyword arguments TABLE and NORMALIZATION
  as usual (see below).

MEMOIZING FUNCTION &KEY TABLE NORMALIZATION
  This takes a function as argument, and returns a new function that
  calls the given FUNCTION when provided arguments for which
  a result wasn't previously memoized.
  Keyword arguments are as usual (see below).
  Note that if function is self-recursive,
  only the toplevel call will be memoized.

MEMOIZED-FUNCALL FUNCTION &REST ARGUMENTS
  This is a generic way to memoize arbitrary functions on a per-call basis:
  all calls to MEMOIZED-FUNCALL share the same cache, which uses
  the EQUAL hash-table *MEMOIZED* below, and no normalization function.

MEMOIZED-APPLY FUNCTION &REST ARGUMENTS
  This function is to MEMOIZED-FUNCALL as APPLY is to FUNCALL.

*MEMOIZED*
  An EQUAL hash-table, the memoized computation cache for MEMOIZED-FUNCALL.
  You may thus easily (clr-hash *memoized*) to clear the cache of all
  such generic memoized function calls.


The keyword arguments TABLE and NORMALIZATION allow users to customize
the behavior of normalization.

TABLE is the hash-table in which to store the memoized computations.
Its keys will be lists of arguments passed to the function, and
its values will be remembered lists of values returned by the function
when previously called with the respective arguments.
The default value if not specified will be a fresh EQUAL hash-table.
The main uses for explicitly specifying such a table is to be able to
clear the table when the computations are somehow invalidated,
or pre-fill the table with seed values,
so the computations terminate when they reach the edge cases.
You'll usually want any such explicitly given table to be otherwise
reachable, for instance by binding a special variable to it.
The hash-table is an EQUAL hash-table by default, but
you can explicitly pass an EQUALP hash-table if you want.
Since the keys are lists (of arguments),
it is inappropriate to use an EQ or EQL hash-table.
If your implementation allows it and it is meaningful,
you may somehow create a hash-table wherein the keys are weak pointers;
how to achieve such an effect is not portable,
see your implementation's documentation.

NORMALIZATION when non-NIL is a function that normalizes argument lists;
the function is called with a continuation and the function arguments,
e.g. with lambda-list (CONTINUATION &REST ARGUMENTS);
it may transform the argument list before to call the continuation with
a normalized argument list that will be used to query the computation cache
and invoke the actual computation function. NIL means no such transformation,
which has the same effect as specifying #'APPLY as a transformation.
Such a function is notably necessary in cases such as the function
having optional arguments or keyword arguments, wherein you might want
to canonicalize the order in which keyword arguments appear, explicitly
fill in the default values for the various arguments, coerce some arguments
to some appropriate type, possibly upcase or downcase some strings, etc.
This may allow you to reduce the size of the memoization table, but also and
most importantly to make sure two semantically equivalent lists of arguments
(according to the semantics of YOUR application) yield the very same result.


==== Other Common Lisp MEMOIZATION libraries ====

Notable precursors published for Common Lisp include the following.

Marty Hall's 1993 memoization package
	http://www.csee.umbc.edu/courses/pub/Memoization/
as notably published as part of Araneida
	http://www.common-lisp.net/project/araneida/araneida-release/memoization.lisp
It tries to do too much, yet fails in some basic cases:
it treats MEMOIZEing as if it were TRACEing, as something temporary,
done to explore existing program behavior, that can be disabled,
and is not required as part of the permanent semantics of your program
(what with allowing to mass-unmemoize all functions? what if a function's
specified memoization table is essential to its termination?).
The way to customize memoization is not very principled, and its proposed
examples and optional optimizations are invitations to writing bad programs.
At the same time, it won't handle multiple return values, and
it will fail silently in presence of inlining.

The version from Peter Norvig's book
"Principles of Artificial Intelligence Programming"
	http://norvig.com/paip/auxfns.lisp
is a nice quick proof of concept, but
not anything anyone would want to use for real.

Tim Bradshaw's memoize library based on the above,
	http://www.tfeb.org/lisp/hax.html#MEMOIZE
will also fail to handle multiple return values,
dubiously offer to clear all memoized functions,
make it hard to use your implementation's weak hash-table feature.
It has a complex memoized-labels of questionable utility;
with fare-memoization, you can use MEMOIZING or MEMOIZED-FUNCALL
to memoize whichever local function you desire without having
to memoize every function in the same labels,
at a scope you have better control upon.

Finally, there's an earlier version of MEMOIZE that I wrote
as part of my own "Fibonacci" discussion and once made part of FARE-UTILS.
	http://fare.tunes.org/files/fun/fibonacci.lisp
FARE-MEMOIZATION is a more elaborate version of it, with an improved API,
notably regarding the TABLE and NORMALIZATION arguments.


As compared to these precursors, fare-memoization tries to:
* do less, providing only what is strictly needed in real-world uses.
* have well-defined semantics in all cases (modulo documented constraints).
* be portable to all compliant CL implementations without hidden assumptions.
* give maximum control to the user in defining memoization tables.
* have a modern packaging, which these days means ASDF and quicklisp.


==== False good idea not implemented by FARE-MEMOIZATION ====

At some point, I wanted to provide a library function as follows:
(define-memo-function make-the (class &rest keys)
  (apply #'make-instance (find-class class) keys))
But there is no portable way to normalize initialization key list:
not only do you have to sort the keys (which can be done portably as below,
assuming they are all keywords), you first have to merge default initform's
for slots -- and because in practice make-instance and shared-initialize
methods are allowed to do things before, after and around the initform's
depending on provided keys, you cannot do that in a portable way at all.

In conclusion, if programmers want to have classes with objects that are
interned in a table that ensures that two objects are EQ if their keys
verify some equality predicate, they have to develop their own protocol.
Things get even murkier when the creation of some object is requested,
but an object already exists that has a similar keys, yet with other
properties not covered by key equality that differ from the previously
interned object. How are the two objects to be reconciled? This also
requires application-dependent semantics that the protocol must allow
the programmer to specify.


Next: , Previous: , Up: Top   [Contents][Index]

2 Systems

The main system appears first, followed by any subsystem dependency.


Previous: , Up: Systems   [Contents][Index]

2.1 fare-memoization

Author

Francois-Rene Rideau

License

MIT

Description

memoizing functions the correct, portable way

Long Description

define memoized functions and memoize previously defined functions

Version

1.2.0

Source

fare-memoization.asd (file)

Component

memoization.lisp (file)


Next: , Previous: , Up: Top   [Contents][Index]

3 Files

Files are sorted by type and then listed depth-first from the systems components trees.


Previous: , Up: Files   [Contents][Index]

3.1 Lisp


Next: , Previous: , Up: Lisp files   [Contents][Index]

3.1.1 fare-memoization.asd

Location

fare-memoization.asd

Systems

fare-memoization (system)


Previous: , Up: Lisp files   [Contents][Index]

3.1.2 fare-memoization/memoization.lisp

Parent

fare-memoization (system)

Location

memoization.lisp

Packages

fare-memoization

Exported Definitions
Internal Definitions

Next: , Previous: , Up: Top   [Contents][Index]

4 Packages

Packages are listed by definition order.


Previous: , Up: Packages   [Contents][Index]

4.1 fare-memoization

Source

memoization.lisp (file)

Nickname

fmemo

Use List

common-lisp

Exported Definitions
Internal Definitions

Next: , Previous: , Up: Top   [Contents][Index]

5 Definitions

Definitions are sorted by export status, category, package, and then by lexicographic order.


Next: , Previous: , Up: Definitions   [Contents][Index]

5.1 Exported definitions


Next: , Previous: , Up: Exported definitions   [Contents][Index]

5.1.1 Special variables

Special Variable: *memoized*
Package

fare-memoization

Source

memoization.lisp (file)


Next: , Previous: , Up: Exported definitions   [Contents][Index]

5.1.2 Macros

Macro: define-memo-function NAME FORMALS &body BODY

Like defun, but creates a memoized function.
Also, if the name is a CONS, then the first element is the name, and the rest is a list of keyword arguments, TABLE and NORMALIZATION as per MEMOIZE.

Package

fare-memoization

Source

memoization.lisp (file)


Previous: , Up: Exported definitions   [Contents][Index]

5.1.3 Functions

Function: memoize SYMBOL &rest KEYS &key TABLE ARGUMENT-NORMALIZER CALL-NORMALIZER NORMALIZATION

Memoize the function associated to given SYMBOL.

Beware that unless the function was declared NOTINLINE, callers may have inlined the original definition and will not see the memoized function.
Moreover, if the function is self-recursive,
this declaration must have happened before it was defined.

Keyword argument TABLE (default: a fresh EQUAL hash-table) lets you
specify an existing hash-table for the memoized computations;
it may have been created with appropriate options regarding equality predicate and weak pointers, initial contents, etc., and you may clear it when needed.

Keyword argument ARGUMENT-NORMALIZER (default: NIL) lets you specify a function taking a list of arguments and returning a normalized list of arguments,
so that all lists with the same normalization will share the same memoized computation. NIL means no such normalization, which is the same as #’LIST.

Keyword argument CALL-NORMALIZER (alias: NORMALIZATION, default: NIL)
lets you specify a function taking a continuation and the function arguments, e.g. with lambda-list (CONTINUATION &REST ARGUMENTS)
which may transform the argument list before to call the continuation
with a normalized argument list that will be used to query the computation cache and invoke the actual computation function; NIL means no such transformation, which has the same effect as specifying #’APPLY as a transformation.

If the function was already being memoized, any previous memoization arguments, i.e. TABLE and ARGUMENT-NORMALIZER, is replaced with the newly specified values (unspecified arguments are replaced by defaults rather than left as previously specified).

Package

fare-memoization

Source

memoization.lisp (file)

Function: memoized-apply FUNCTION &rest ARGUMENTS
Package

fare-memoization

Source

memoization.lisp (file)

Function: memoized-funcall &rest ARGUMENTS
Package

fare-memoization

Source

memoization.lisp (file)

Function: memoizing FUNCTION &rest KEYS &key TABLE NORMALIZATION

Given a function, return a memoizing version of same function. Keyword arguments TABLE and NORMALIZATION are as per MEMOIZE.

Package

fare-memoization

Source

memoization.lisp (file)

Function: unmemoize SYMBOL

undoing the memoizing function, return the memoization-info record for the function

Package

fare-memoization

Source

memoization.lisp (file)

Function: unmemoize-1 SYMBOL &rest ARGUMENTS

Forget the memoized result of calling SYMBOL with arguments ARGUMENTS. Do not forget memoized results of calling the function with other arguments. Returns T if a stored result was found and removed, NIL otherwise.

Package

fare-memoization

Source

memoization.lisp (file)


Previous: , Up: Definitions   [Contents][Index]

5.2 Internal definitions


Next: , Previous: , Up: Internal definitions   [Contents][Index]

5.2.1 Functions

Function: compute-memoized-function INFO ARGUMENTS

the basic helper for computing with a memoized function described by INFO, being called with arguments ARGUMENTS

Package

fare-memoization

Source

memoization.lisp (file)

Function: make-memoization-info FUNCTION &rest KEYS &key TABLE ARGUMENT-NORMALIZER CALL-NORMALIZER NORMALIZATION
Package

fare-memoization

Source

memoization.lisp (file)

Function: memoization-wrapper INFO

the basic helper for computing with a memoized function described by INFO, being called with arguments ARGUMENTS

Package

fare-memoization

Source

memoization.lisp (file)


Next: , Previous: , Up: Internal definitions   [Contents][Index]

5.2.2 Generic functions

Generic Function: memoized-argument-normalizer OBJECT
Package

fare-memoization

Methods
Method: memoized-argument-normalizer (MEMOIZATION-INFO memoization-info)

either NIL or a function to normalize arguments before memoization

Source

memoization.lisp (file)

Generic Function: memoized-call-normalizer OBJECT
Package

fare-memoization

Methods
Method: memoized-call-normalizer (MEMOIZATION-INFO memoization-info)

either NIL or a function to normalize arguments before memoization

Source

memoization.lisp (file)

Generic Function: memoized-table OBJECT
Package

fare-memoization

Methods
Method: memoized-table (MEMOIZATION-INFO memoization-info)

a hash-table containing the memoized computations so far

Source

memoization.lisp (file)

Generic Function: original-function OBJECT
Package

fare-memoization

Methods
Method: original-function (MEMOIZATION-INFO memoization-info)

The original, unmemoized, function

Source

memoization.lisp (file)

Generic Function: wrapped-function OBJECT
Generic Function: (setf wrapped-function) NEW-VALUE OBJECT
Package

fare-memoization

Methods
Method: wrapped-function (MEMOIZATION-INFO memoization-info)
Method: (setf wrapped-function) NEW-VALUE (MEMOIZATION-INFO memoization-info)

The memoizing version of the function.

Source

memoization.lisp (file)


Previous: , Up: Internal definitions   [Contents][Index]

5.2.3 Classes

Class: memoization-info ()

information about a function that was memoized

Package

fare-memoization

Source

memoization.lisp (file)

Direct superclasses

standard-object (class)

Direct methods
Direct slots
Slot: function

The original, unmemoized, function

Initargs

:function

Readers

original-function (generic function)

Slot: wrapped-function

The memoizing version of the function.

Readers

wrapped-function (generic function)

Writers

(setf wrapped-function) (generic function)

Slot: table

a hash-table containing the memoized computations so far

Initargs

:table

Initform

(make-hash-table :test (quote equal))

Readers

memoized-table (generic function)

Slot: argument-normalizer

either NIL or a function to normalize arguments before memoization

Initargs

:argument-normalizer

Readers

memoized-argument-normalizer (generic function)

Slot: call-normalizer

either NIL or a function to normalize arguments before memoization

Initargs

:normalization, :call-normalizer

Readers

memoized-call-normalizer (generic function)


Previous: , Up: Top   [Contents][Index]

Appendix A Indexes


Next: , Previous: , Up: Indexes   [Contents][Index]

A.1 Concepts

Jump to:   F   L  
Index Entry  Section

F
fare-memoization.asd: The fare-memoization<dot>asd file
fare-memoization/memoization.lisp: The fare-memoization/memoization<dot>lisp file
File, Lisp, fare-memoization.asd: The fare-memoization<dot>asd file
File, Lisp, fare-memoization/memoization.lisp: The fare-memoization/memoization<dot>lisp file

L
Lisp File, fare-memoization.asd: The fare-memoization<dot>asd file
Lisp File, fare-memoization/memoization.lisp: The fare-memoization/memoization<dot>lisp file

Jump to:   F   L  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.2 Functions

Jump to:   (  
C   D   F   G   M   O   U   W  
Index Entry  Section

(
(setf wrapped-function): Internal generic functions
(setf wrapped-function): Internal generic functions

C
compute-memoized-function: Internal functions

D
define-memo-function: Exported macros

F
Function, compute-memoized-function: Internal functions
Function, make-memoization-info: Internal functions
Function, memoization-wrapper: Internal functions
Function, memoize: Exported functions
Function, memoized-apply: Exported functions
Function, memoized-funcall: Exported functions
Function, memoizing: Exported functions
Function, unmemoize: Exported functions
Function, unmemoize-1: Exported functions

G
Generic Function, (setf wrapped-function): Internal generic functions
Generic Function, memoized-argument-normalizer: Internal generic functions
Generic Function, memoized-call-normalizer: Internal generic functions
Generic Function, memoized-table: Internal generic functions
Generic Function, original-function: Internal generic functions
Generic Function, wrapped-function: Internal generic functions

M
Macro, define-memo-function: Exported macros
make-memoization-info: Internal functions
memoization-wrapper: Internal functions
memoize: Exported functions
memoized-apply: Exported functions
memoized-argument-normalizer: Internal generic functions
memoized-argument-normalizer: Internal generic functions
memoized-call-normalizer: Internal generic functions
memoized-call-normalizer: Internal generic functions
memoized-funcall: Exported functions
memoized-table: Internal generic functions
memoized-table: Internal generic functions
memoizing: Exported functions
Method, (setf wrapped-function): Internal generic functions
Method, memoized-argument-normalizer: Internal generic functions
Method, memoized-call-normalizer: Internal generic functions
Method, memoized-table: Internal generic functions
Method, original-function: Internal generic functions
Method, wrapped-function: Internal generic functions

O
original-function: Internal generic functions
original-function: Internal generic functions

U
unmemoize: Exported functions
unmemoize-1: Exported functions

W
wrapped-function: Internal generic functions
wrapped-function: Internal generic functions

Jump to:   (  
C   D   F   G   M   O   U   W  

Next: , Previous: , Up: Indexes   [Contents][Index]

A.3 Variables

Jump to:   *  
A   C   F   S   T   W  
Index Entry  Section

*
*memoized*: Exported special variables

A
argument-normalizer: Internal classes

C
call-normalizer: Internal classes

F
function: Internal classes

S
Slot, argument-normalizer: Internal classes
Slot, call-normalizer: Internal classes
Slot, function: Internal classes
Slot, table: Internal classes
Slot, wrapped-function: Internal classes
Special Variable, *memoized*: Exported special variables

T
table: Internal classes

W
wrapped-function: Internal classes

Jump to:   *  
A   C   F   S   T   W  

Previous: , Up: Indexes   [Contents][Index]

A.4 Data types

Jump to:   C   F   M   P   S  
Index Entry  Section

C
Class, memoization-info: Internal classes

F
fare-memoization: The fare-memoization system
fare-memoization: The fare-memoization package

M
memoization-info: Internal classes

P
Package, fare-memoization: The fare-memoization package

S
System, fare-memoization: The fare-memoization system

Jump to:   C   F   M   P   S