0

これらの手順を実行しようとすると、電話するまですべて問題ないようです

 (set! fib (mem 'memorize fib))
 (fib 10)
 (fib 10)
 (set! fib (mem 'unmemorize fib))
 (fib 4)

'memorize TO' unmemorize を変更した後、何が起こるかというと、両方を実行するということです。

(define (mem mem-it func)
  (let ((table (make-table)))
    (case mem-it
      ((memoize)
       (display " --- memoize ---\n")
       (lambda (args)
         (let ((prev-com-res (lookup args table))) ;; prev-com-res = previously-computed-result
           (display " --- memoize2 ---\n")
           (or prev-com-res                            
               (let ((result (func args)))                  
                 (insert! args result table)
                 result)))))
      ((unmemoize)
       (display " --- unmemoize --- \n")
       (lambda (args)
         (let ((comp (func args)))
           comp)))
      (else
       (display " -- Unknown command! --\n")))))

「unmemoize」を呼び出すタイミングがわかりません。memoize にも入ります = S

4

3 に答える 3

1

問題は、あなたが電話をかけたときに、最初の行でメモした(mem 'unmemoize fib)ものを渡していることです!fib

これを行います[申し訳ありませんが、この「修正」は間違っています]

(define (mem mem-it func)
  (let ((table (make-table))
        (original-func func))     ;; added
    (case mem-it
      ((memoize)
       (display " --- memoize ---\n")
       (lambda (args)
         (let ((prev-com-res (lookup args table))) ;; prev-com-res = previously-computed-result
           (display " --- memoize2 ---\n")
           (or prev-com-res                            
               (let ((result (func args)))                  
                 (insert! args result table)
                 result)))))
      ((unmemoize)
       (display " --- unmemoize --- \n")
       original-func)                   ;; changed
      (else
       (display " -- Unknown command! --\n")))))
于 2013-04-25T19:04:09.123 に答える
0

OK、問題はすでに診断されています。ここに解決策があります。

メモ化された関数は、いくつかの引数を受け取ります (さもなければ、メモ化するものは何もありません)。つまり、元の関数を復元するために、引数なしの呼び出しを使用できます。

(define (mem mem-it func)
    (case mem-it
      ((memoize)
       (display " --- memoize ---\n")
       (let ((table (make-table)))                 ;; changed
        (lambda args   (if (null? args) func       ;; changed 
         (let ((prev-com-res (lookup args table))) 
           (display " --- memoize2 ---\n")
           (or prev-com-res                            
               (let ((result (apply func args)))   ;; changed             
                 (insert! args result table)
                 result)))))))                     ;; changed
      ((unmemoize)
       (display " --- unmemoize --- \n")
       (func))                                     ;; changed 
      (else
       (display " -- Unknown command! --\n"))))

形式のラムダ式は、(lambda args ...body...)すべての引数をリストに収集します。例えば:

(define qq (lambda args args))
;Value: qq

(qq 1 2 3)
;Value 12: (1 2 3)

Barmar がコメントで正しく指摘しているように、これは、引数のない呼び出しが意味を持つ可変数の引数を持つ関数では機能しません。しかし、他のすべての場合、それは機能します。ただし、すべての場合に機能させることも可能です。特別なシンボルを定義し、それをチェックしeq?て回復をトリガーする必要があります。

(define mem
 (let ((trigger (list 'trigger))                
       (check   (list 'check))) 
  (lambda (mem-it func)                               ;; changed
    (case mem-it
      ((memoize)
       (display " --- memoize ---\n")
       (let ((table (make-table)))                    ;; changed
        (lambda args   (if (eq? check trigger) func   ;; changed 
         (let ((prev-com-res (lookup args table))) 
           (display " --- memoize2 ---\n")
           (or prev-com-res                            
               (let ((result (apply func args)))      ;; changed 
                 (insert! args result table)
                 result)))))))                        ;; changed
      ((unmemoize)
       (display " --- unmemoize --- \n")
       (let ((c check))                            ;; changed...
         (set! check trigger)  ;; or: (fluid-let ((check trigger))
         (let ((f (func)))     ;;       (func))
           (set! check c)
           f)))                                    ;; ...changed
      (else
       (display " -- Unknown command! --\n"))))))

これは、引数が考慮される前でも機能します。

于 2013-05-01T12:32:03.307 に答える
0

あなたがしなければならないことは、元の定義をどこかに保存して、メモを解除するときにそれを復元できるようにすることです。

(define *original-functions* (make-table))

(define (mem mem-it func)
  (let ((table (make-table))
        (original-func func))     ;; added
    (case mem-it
      ((memoize)
       (display " --- memoize ---\n")
       (let ((new-func
              (lambda args
                (let ((prev-com-res (lookup args table))) ;; prev-com-res = previously-computed-result
                  (display " --- memoize2 ---\n")
                  (or prev-com-res                            
                      (let ((result (apply func args)))                  
                        (insert! args result table)
                        result))))))
         (insert! new-func original-func *original-functions*)
         new-func))
      ((unmemoize)
       (display " --- unmemoize --- \n")
       (lookup func *original-functions*))
      (else
       (display " -- Unknown command! --\n")))))
于 2013-05-01T16:08:15.037 に答える