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

The problem is that when you call (mem 'unmemoize fib) you are passing fib which you memoized in your first line!

Do this [Sorry this 'fix' is wrong]

(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

好的,所以您已经诊断出了问题,这就是解决方案。

任何记忆化的函数都会接收一些参数(否则我们将没有任何东西可以记忆它)。这意味着我们可以使用不带参数的调用来恢复原始函数:

(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 表达式将(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 回答