Scheme中的一般记忆程序

时间:2015-04-19 12:30:10

标签: scheme memoization sicp r5rs

我正在尝试在Scheme中创建一个通用的memoization过程。这就是我到目前为止(它与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','插入!'以及'查找'程序在SICP书籍中定义)

如果我用一个只带一个参数的过程调用这个方法,它就可以了。我无法弄清楚如何使用一个带有0个或多个参数的过程。

我找到了这个链接:http://community.schemewiki.org/?memoization,但我还是无法让它发挥作用。链接中的过程使用应用值和值调用,即使我对它们的工作方式有了大致的了解,但我似乎无法将其与我的过程集成。

 (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)))))))

这是我尝试使用列表从链接开始的过程。它几乎可以正常工作,但是如果我有一个带有多个参数的过程,它会多次计算它。让我们说我通过一个随机程序参数1 2 3 4.它将在表中保存1 2 3 4,但不会分别给出1,2,3和4的给定结果。我想我的错误是我查找的地方,因为我立刻传递了整个列表。

编辑:添加了mem2无法正常使用的testprocedure。

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

它将在查询表中保存整个' args'。如果我有:

  

(定义add(mem2 add))

     

(加2 3 4)

     

计算添加(2 3 4)

     

计算添加(3 4)

     

计算添加(4)

     

9

     

(加3)

     

计算添加(3)

1 个答案:

答案 0 :(得分:1)

(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个之前没有打印过这个例子 表明结果已被记忆。