views:

130

answers:

1

I am facing a couple of problems while writing an auto-memoizer in Scheme.

I have a working memoizer function, which creats a hash table and checks if the value is already computed. If it has been computed before then it returns the value else it calls the function.

(define (memoizer fun)
  (let ((a-table (make-hash)))
    (λ(n)
      (define false-if-fail (λ() #f))
      (let ((return-val (hash-ref a-table n false-if-fail)))
        (if return-val
            return-val
            (begin
              (hash-set! a-table n (fun n))
              (hash-ref a-table n)))))))

Now I want to create a memoize-wrapper function like this:

(define (memoize-wrapper function)
  (set! function (memoizer function)))

And hopefully create a macro called def-memo which defines the function with the memoize-wrapper. eg. the macro could expand to (memoizer (define function-name arguments body ...) or something like that.

So that I should be able to do :

(def-memo (factorial n)
  (cond
    ((= n 1) 1)
    (else (* n (factorial (- n 1))))))

which should create a memoized version of the factorial instead of the normal slow one.

My problem is that the

  1. The memoize-wrapper is not working properly, it doesnt call the memoized function but the original function.
  2. I have no idea how to write a define inside of the macro. How do I make sure that I can get variable lenght arguments and variable length body? How do I then define the function and wrap it around with the memoizer?

Thanks a lot.

+4  A: 

this is what i use in PLT scheme:

#lang scheme

(define (memo f)
  (define mh (make-hash))
  (lambda p
    (hash-ref mh p (lambda ()
                     (hash-set! mh p (apply f p))
                     (hash-ref mh p)))))

(define-syntax-rule (defmemo (id . p) . body)
  (define id (memo (lambda p . body))))

(provide defmemo)
Javier
WOW. That is just awesome. Could you briefly comment your code especially the macro bit. Why are there . ? why did you provide? And do you really need apply? I am a newbie. Thanks.
kunjaan
In a parameter list, . indicates that the following variable is bound to more than one thing. In the macro, p is a list of params, not just a single param (body is a list of expressions). Same thing in the function, apply is needed to apply p, a list of params, to the function f.
Nathan Sanders
Eli Barzilay
Oh, and BTW, note that memoization is not always so straightforward; you might want to memoize based on argument identities (eg, use an `eq?` hash table), or only on some arguments, or use a weak hash table to avoid memory leaks, etc etc. Also, the above solution might be slow for various reasons (like using a rest argument, or a single hash table for the lookup of all arguments which can mean a very loaded table).
Eli Barzilay
Thanks a lot Nathan and Eli.
kunjaan