Scheme 中的一般记忆过程

General memoization procedure in Scheme

我正在尝试在 Scheme 中创建一个通用的记忆程序。这是我目前所拥有的(与 SICP 书中的练习 3.27 几乎完全相同):

(define (memo proc)
  (let ((table (make-table)))
    (lambda (args)
      (let ((prev (lookup args table)))
        (or prev
            (let ((result (proc args)))
              (insert! args result table)
              result))))))

('make-table'、'insert!' 和 'lookup' 过程在 SICP 书中定义)

如果我用一个只接受一个参数的过程调用这个方法,它工作得很好。我不知道该怎么做是让它与一个带有 0 个或多个参数的过程一起工作。

我找到了 link: http://community.schemewiki.org/?memoization ,但我仍然无法使用它。 link 中的过程使用应用值和调用值,尽管我对它们的工作原理有一个粗略的了解,但我似乎无法将它与我的过程集成。

 (define (mem2 proc)
   (let ((table (make-table)))
        (lambda args
          (let ((prev (lookup args table)))
            (or prev
                (call-with-values
                 (lambda () (apply proc args))
                 (lambda (result)
                   (insert! args result table)
                   result)))))))

这是我对来自 link 的程序的尝试,使用了一个列表。它几乎可以工作,但如果我有一个带有多个参数的过程,它将计算多次。假设我将参数 1 2 3 4 传递给一个随机过程。它将在 table 中保存 1 2 3 4,但不会分别保存 1、2、3 和 4 的给定结果。我想我的错误是我在哪里查找,因为我一次通过了整个列表。

编辑:添加了 mem2 不能正常工作的测试程序。

(define (add . args)
  (display "computing add of ")
  (display args) (newline)
  (if (null? args)
      0
      (+ (car args) (apply add (cdr args)))))

它将在查找 table 中保存整个 'args'。所以如果我有:

(define add (mem2 add))

(add 2 3 4)

computing add of (2 3 4)

computing add of (3 4)

computing add of (4)

9

(add 3)

computing add of (3)

(define (make-table)
  (vector '()))

(define (insert! key val t)
  (vector-set! t 0 (cons (cons key val) (vector-ref t 0))))

(define (lookup key t)
  (let ([result (assoc key (vector-ref t 0))])
    (and result (cdr result))))

(define (mem2 proc)
  (let ((table (make-table)))
    (lambda args
      (let ((prev (lookup args table)))
        (or prev
            (let ([result (apply proc args)])
              (insert! args result table)
              result))))))

(define (plus x y)
  (display (list "Computing sum of: " x y))
  (newline)
  (+ 1 2))

(define memo-plus (mem2 plus))

(memo-plus 1 2)
(memo-plus 1 2)

输出:

(Computing sum of:  1 2)
3
3

添加:

(define (add . args)
  (display "computing add of ")
  (display args) (newline)
  (if (null? args)
      0
      (+ (car args) (apply add (cdr args)))))

(define memo-add (mem2 add))

(memo-add 1 2 3 4)
(memo-add 1 2 3 4)

给出输出:

computing add of (1 2 3 4)
computing add of (2 3 4)
computing add of (3 4)
computing add of (4)
computing add of ()
10
10

由于在最后 10 之前没有打印任何内容,因此示例 表明结果已被记忆。