 
 
 
 
 
   
 Next: 8.2 結果記憶型関数を定義するマクロの定義
Up: 8 クロージャによる結果記憶型関数(memoization)の実現
 Previous: 8 クロージャによる結果記憶型関数(memoization)の実現
 
ユーザが定義する関数を記憶型の関数に変換するプログラムは,この対のデー
タをユーザの関数ごとに記憶する必要があります.このデータを記憶するため
にいちいち大域変数を用意するのではなく,もとの関数を記憶型に変換した関
数データを返すことにし,対の記憶データはクロージャの中に蓄えることで実
現が可能になります.
 
(defun memo (fn)
  (let (alist)
    #'(lambda (x)
        (let ((result (assoc x alist)))
          (cond
           ((null result)
            (setq result (funcall fn x))
            (setq alist (cons (cons x result) alist))
            result)
           (t (cdr result)))))))
このmemo関数にfibを渡して記憶型のfibを定義することができます.
 
> (setq fib-memo (memo #'fib))
...
> (funcall fib-memo 4)
 0: (FIB 3)
   1: (FIB 2)
     2: (FIB 1)
     2: returned 1
     2: (FIB 0)
     2: returned 1
   1: returned 2
   1: (FIB 1)
   1: returned 1
 0: returned 3
 0: (FIB 2)
   1: (FIB 1)
   1: returned 1
   1: (FIB 0)
   1: returned 1
 0: returned 2
5
このfib-memoを実行してもfib自体が変更されていないために,
トップレベルの実行結果のみしか蓄積されません.
そこでfib-memoをfib本体として定義してしまえば良いわけです.
 
> (setf (symbol-function 'fib) fib-memo)
#<Function FIB @ #x900a76> 
> (fib 5)
 0: (FIB 5)
   1: (FIB 4)
   1: returned 5
   1: (FIB 3)
   1: returned 3
 0: returned 8
8 
> (fib 6)
 0: (FIB 6)
   1: (FIB 5)
   1: returned 8
   1: (FIB 4)
   1: returned 5
 0: returned 13
13
このようにfibが下請けの計算をいちいちせずに関数を用意している
ことがわかります.
 
generated through LaTeX2HTML. M.Inaba 平成18年5月6日