Я делаю SICP ex 3.52. Я получаю правильные ответы на выражения «stream-ref» и «display-stream», а также получаю правильное значение «sum» после каждого выражения, данного в упражнении. Однако все это работает без использования оптимизации «memo-proc», представленной на странице 439 непосредственно перед перечисленным упражнением.
Я использую Guile в Linux, и единственным другим дополнением, которое я сделал в коде, было определение синтаксиса в верхней части кода для «cons-stream», включающее форму «задержки».
Возможно, я что-то неправильно понимаю, но я даже не вижу точки, в которой в исполнении вызывается "memo-proc". Есть ли что-то, что встроено в Guile, которое уже выполняет эту оптимизацию, обеспечиваемую "memo-proc", которая, согласно SICP, служит для реализации "задержки" в качестве специальной запоминающейся процедуры.
Вот запомненная процедура в SICP ...
(define (memo-proc proc)
(let ((already-run? false) (result false))
(lambda ()
(if (not already-run?)
(begin (set! result (proc))
(set! already-run? true)
result)
result))))
Код для удобства ...
(define (stream-ref s n)
(if (= n 0)
(stream-car s)
(stream-ref (stream-cdr s) (- n 1))))
(define (stream-map proc . argstreams)
(if (stream-null? (car argstreams))
the-empty-stream
(cons-stream
(apply proc (map stream-car argstreams))
(apply stream-map
(cons proc (map stream-cdr argstreams))))))
(define (stream-for-each proc s)
(if (stream-null? s)
'done
(begin (proc (stream-car s))
(stream-for-each proc (stream-cdr s)))))
(define (display-stream s)
(stream-for-each display-line s))
(define (display-line x) (newline) (display x))
(define (stream-car stream) (car stream))
(define (stream-cdr stream) (force (cdr stream)))
(define (stream-enumerate-interval low high)
(if (> low high)
the-empty-stream
(cons-stream
low
(stream-enumerate-interval (+ low 1) high))))
(define (stream-filter pred stream)
(cond ((stream-null? stream) the-empty-stream)
((pred (stream-car stream))
(cons-stream (stream-car stream)
(stream-filter
pred
(stream-cdr stream))))
(else (stream-filter pred (stream-cdr stream)))))
И последовательность выражений для упражнения ...
(define sum 0)
(define (accum x) (set! sum (+ x sum)) sum)
(define seq
(stream-map accum
(stream-enumerate-interval 1 20)))
(define y (stream-filter even? seq))
(define z
(stream-filter (lambda (x) (= (remainder x 5) 0))
seq))
(stream-ref y 7)
(display-stream z)
Я ожидаю результатов, перечисленных ниже, и получаю их.
(define sum 0)
;; sum => 0
(define (accum x)
(set! sum (+ x sum))
sum)
;; sum => 0
(define seq (stream-map accum (stream-enumerate-interval 1 20)))
;; sum => 1
(define y (stream-filter even? seq))
;; sum => 6
(define z (stream-filter (lambda (x) (= (remainder x 5) 0))
seq))
;; sum => 10
(stream-ref y 7)
;; sum => 136
;; => 136
(display-stream z)
;; sum => 210
;; => (10 15 45 55 105 120 190 210)
Однако я получаю эти результаты, не используя "memo-proc". Однако без оптимизации "memo-proc" я бы ожидал получить "сумму" 15 при:
(define z (stream-filter (lambda (x) (= (remainder x 5) 0))
seq))
;; sum => 10
потому что функция «накапливается» будет вызываться дополнительные времена, так как часть потока «seq» должна быть перечислена во второй раз. Я надеюсь, что кто-то может помочь мне увидеть, что мне не хватает.