SICP中的cons-stream是如何实现的?

7

我正在学习《scip》中的流部分,目前遇到了如何定义流的问题。

以下是我的代码:

(define (memo-func function)
  (let ((already-run? false)
        (result false))
    (lambda ()
      (if (not already-run?)
          (begin (set! result (function))
                 (set! already-run? true)
                 result)
          result))))


(define (delay exp)
  (memo-func (lambda () exp)))

(define (force function)
  (function))

(define the-empty-stream '())
(define (stream-null? stream) (null? stream))
(define (stream-car stream) (car stream))
(define (stream-cdr stream) (force (cdr stream)))

(define (cons-stream a b) (cons a (memo-func (lambda () b))))

如果我按照书中的描述定义整数:
(define (integers-starting-from n)
   (cons-stream n (integers-starting-from (+ n 1))))
(define integers (integers-starting-from 1))

我收到一条消息,内容为:“中止!:超出最大递归深度。”

我猜测“延迟”函数不起作用,但我不知道如何修复它。我在我的Mac上运行MIT方案。

更新1

现在使用宏cons-stream,可以定义整数。

但是我又遇到了另一个错误。

(define (stream-take n s)
  (cond ((or (stream-null? s)
             (= n 0)) the-empty-stream)
        (else (cons-stream (stream-car s)
                           (stream-take (- n 1) (stream-cdr s))))))

(stream-take 10 integers)
;ERROR - Variable reference to a syntactic keyword: cons-stream

更新2

请忽略上面的更新1


4
我是 SRFI-41 Streams 的作者,该流提供与 SICP 不同的流类型(并解释了其中的区别)。请在 SRFI 网站(http://srfi.schemers.org/srfi-41/)或我的博客(http://programmingpraxis.com/2013/01/29/essay-srfi-41-streams/)上查看。 - user448810
2个回答

8

cons-stream需要是一个宏才能使你的示例代码正确运行。否则,对cons-stream的调用将会急切地评估其所有参数。

尝试这个(未经测试):

(define-syntax cons-stream
  (syntax-rules ()
    ((cons-stream a b)
     (cons a (memo-func (lambda () b))))))

顺便提一句,您的delay也需要成为宏,原因与前面类似。在您修复delay之后,可以直接使用delay来制作cons-stream


实际上,我知道发生了什么。我忘记使用更改后的cons-stream定义重新评估cons-stream。 - zcaudate
2
这里有一篇新手或和我一样入门的人的 SICP 面包屑。以下文章是一个有关 delay 无毁性更新的微型研讨会,展示了它的优缺点:https://github.com/VincentToups/emacs-utils/blob/master/delay.md这是我发现的第一个这样的讨论。看起来已经足够了。就我所知,为什么我们可能在 delay 中使用毁性更新的问题可能已经在 SICP 本身中得到很好的解答。它也可能在 Stack Overflow 或 programmers.stackexchange.com 的某个地方得到很好的解答。 - minopret

2

你不能将延迟定义为函数,因为在调用它之前,Scheme会评估其参数 - 这正是你试图推迟的内容。《计算机程序的构造和解释》明确指出,delay应该是一个特殊形式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接