I have made this memoize function bellow and I am experimenting with it.
(define (make-table)
(list '*table*))
(define (lookup key table)
(let ((record (assoc key (cdr table))))
(and record (cdr record))))
(define (insert! key value table)
(let ((record (assoc key (cdr table))))
(if record
(set-cdr! record value)
(set-cdr! table
(cons (cons key value) (cdr table))))))
(define (fib n)
(display "computing fib of ")
(display n) (newline)
(cond ((= n 0) 0)
((= n 1) 1)
(else (+ (fib (- n 1))
(fib (- n 2))))))
(define (memoize message f)
(define (dispatch message)
(cond
((eq? message 'memoize) memo)
((eq? message 'unmemoize) fibe)))
(define memo
(let ((table (make-table)))
(lambda (x)
(let ((previously-computed-result (lookup x table)))
(or previously-computed-result
(let ((result (f x)))
(insert! x result table)
result)
)))))
(dispatch message) )
You can ignore the 'unmemoize) fibee part.
What I have a hard time understanding is why these two lines of codes bellow don't act in the same way.
(set! fib(memoize 'memoize fib))
and
(define mm (memoize 'memoize fib))
fib here is this function:
(define (fib n)
(cond ((= n 0) 0)
((= n 1) 1)
(else (+ (fib (- n 1))
(fib (- n 2))))))
Calling these functions bellow gives me different results and I don't understand why
(fib 3)
(fib 3)
(mm 3)
(mm 3)
Result:
calling (mm 3 ) twice and (mm 2) once

As you can see (mm 3) and (fib 3) act differently, and when I run (mm 2) I don't see why we don't just get the number 1 as return but new computation

The problem is that when you do
(define mm (memoize 'memoize fib)),mmcalls a memoized version offib, butfibitself is defined to recursively call itself, andfibis not memoized. That is, whenmmis called, only the initial call tofibis subject to memoization.This can be seen by using a
tracefunctionality. It appears that the posted code is not Racket, but instead#lang r5rs, which allows access to Racket'straceprocedure with(#%require racket/trace). We can use this to see the calls tofibas they unfold. Note that I commented out thedisplaycalls in OP definition offibto remove some noise in the output:This produces exactly the same trace, which I will omit here to save space:
When
mmis called the memoized version offibis called once, and then the unmemoizedfibis called many times.With
(set! fib (memoize 'memoize fib))things are different. This timememoizereturns a memoized version offib, and the symbolfibis mutated so that it refers to this memoized version! Now wheneverfibis called, it is the memoized version that is called, and this includes recursive calls:Here you can see the difference by comparing the trace for
fibbefore and after setting it to the memoized version.For some further reading, here is a related answer that I wrote some time ago.