caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Andrej Bauer <Andrej.Bauer@andrej.com>
To: caml-list@inria.fr
Cc: Erik de Castro Lopo <mle+ocaml@mega-nerd.com>
Subject: Re: [Caml-list] Memoization
Date: Sat, 09 Sep 2006 05:38:11 +0200	[thread overview]
Message-ID: <45023723.2050708@andrej.com> (raw)
In-Reply-To: <20060909103332.0397efea.mle+ocaml@mega-nerd.com>

Erik de Castro Lopo wrote:
> 
> Unfortunately, the URL is dead. Does anybody have another link for
> that code or some other polymorphic memoizer?
> 

I use the code below to show my students what can be done with
higher-order functions. For a real implementation, we would have to use
something more efficient than association lists (but then you might end
up writing a polymorphic version of the Map module). Improvements are
welcome.

--------------------
(** [memo f] is a memoized version of function [f]. If [f] makes
recursive calls, those are not memoized. In this example we use simple
asociation lists. It would be better to use efficietn search trees.
Alas, ocaml Map module is not polymorphic (for a good reason?). *)

let memo f =
  let m = ref [] in
    fun x ->
      try
	List.assoc x !m
      with
	  Not_found ->
	    let y = f x in
	      m := (x, y) :: !m ;
	      y


(** [memo_rec f] is a memoized version of a recursive function [f].
The recursive function must not make calls to itself directly, but
rather via an extra "self" parameter, see example below. *)

let memo_rec f =
  let m = ref [] in
  let rec g x =
    try
      List.assoc x !m
    with
	Not_found ->
	  let y = f g x in
	    m := (x, y) :: !m ;
	    y
  in
    g

(** [memo_test f stamp renew] is a memoized version of function [f],
where [stamp] and [renew] are used to invalidate memoized values and
force them being recomputed. For example, [f] could be a function
which reads the contents of a file, [stamp] the function which returns
the file's modification time, and [renew] the function which compares
two modification times. Note that we keep storing new values in an
association list without removing old ones, so this creates a memory
leak. An intelligent implementation would, again, use efficient search
trees. *)

let memo_test f stamp renew =
  let m = ref [] in
    fun x ->
      try
	let y, s = List.assoc x !m in
	let t = stamp x in
	  if renew s t then
	    let y = f x in
	      m := (x, (y, t)) :: !m ; y
	  else
	    y
      with
	  Not_found ->
	    let y = f x in
	    let s = stamp x in
	      m := (x, (y, s)) :: !m; y


(** Example: the Fibonacci sequence, unmemoized, very inefficient. *)
let rec fib_slow = function
    0 -> 1
  | 1 -> 1
  | n -> fib_slow (n - 1) + fib_slow (n - 2)

(** Example: a memoized version of the Fibonacci sequence. *)
let fib_memo =
  let rec fib self = function
      0 -> 1
    | 1 -> 1
    | n -> self (n - 1) + self (n - 2)
  in
    memo_rec fib
--------------------


  reply	other threads:[~2006-09-09  4:10 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-09-09  0:33 Memoization Erik de Castro Lopo
2006-09-09  3:38 ` Andrej Bauer [this message]
2006-09-09  7:56   ` [Caml-list] Memoization Erik de Castro Lopo
2006-09-09 15:47     ` Mike Lin
2006-09-09 21:20 ` William Neumann
2006-10-06  3:22   ` Walid Taha
2006-09-30  8:49 ` Jan Kybic

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=45023723.2050708@andrej.com \
    --to=andrej.bauer@andrej.com \
    --cc=caml-list@inria.fr \
    --cc=mle+ocaml@mega-nerd.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).