Я делаю 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
потому что функция «accum» будет вызываться несколько раз, так как часть потока «seq» нужно будет перечислить во второй раз. Я надеюсь, что кто-то может помочь мне увидеть, что мне не хватает.