【问题标题】:Running code from SICP section 3.5.4 with DrRacket使用 DrRacket 运行 SICP 第 3.5.4 节中的代码
【发布时间】:2012-12-09 12:29:47
【问题描述】:

我在运行 SICP(计算机程序的结构和解释)第 3.5.4 节(流和延迟评估)中的示例代码时遇到问题; SICP 部分可以在这里找到:http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-24.html#%_sec_3.5.4

我正在使用 DrRacket 版本 5.2.1,使用 Neil Van Dyke 的 SICP 支持语言 (SICP PLaneT 1.17) 设置,可在此处找到:http://www.neilvandyke.org/racket-sicp/#%28part._installation%29

如下所示的代码使用了流。如上所述设置环境后,DrRacket 已经可以使用程序cons-streamforcedelay。但是stream-carstream-cdr 不可用;所以,我必须定义它们。在下面的代码中,我还定义了一些通用的流函数:stream-mapstream-refadd-streamsscale-stream

我正在尝试制作的整个代码如下。它包括使用积分程序 (integral) 以数值方式求解一阶微分方程的程序 (solve),该程序使用延迟参数 (delayed-integrand);这些过程来自第 3.5.4 节。

(define (stream-car stream) (car stream))
(define (stream-cdr stream) (force (cdr stream)))
(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-ref s n)
  (if (= n 0)
      (stream-car s)
      (stream-ref (stream-cdr s) (- n 1))))

(define (add-streams s1 s2)
  (stream-map + s1 s2))

(define (scale-stream stream factor)
  (stream-map (lambda (x) (* x factor)) stream))

(define (integral delayed-integrand initial-value dt)
  (define int
    (cons-stream initial-value
                 (let ((integrand (force delayed-integrand)))
                   (add-streams (scale-stream integrand dt)
                                int))))
  int)

(define (solve f y0 dt)
  (define y (integral (delay dy) y0 dt))
  (define dy (stream-map f y))
  y)

当我将上面的定义放入 DrRacket 并单击运行时,没有出现错误。但是,当我尝试在交互窗口中执行以下行时出现错误:

(stream-ref (solve (lambda (y) y) 1 0.001) 1000)

错误信息是:

mcar: expects argument of type <mutable-pair>; given #<undefined>

出现此错误时,DrRacket 会高亮显示程序stream-car 的定义体,如下图所示:


是什么导致了这个错误?我已经在前面的示例中使用了上面的流过程(stream-carstream-cdrstream-mapadd-streamsscale-stream)并且它们有效。当我在solve 程序之外使用它时,integral 程序也可以工作;例如,如果我定义(define ones (cons-stream 1 ones)),然后我定义(define s (integral (delay ones) 1 1)),然后我执行(stream-ref s 1000),它正确地给出了输出1001

【问题讨论】:

    标签: scheme sicp racket


    【解决方案1】:

    您报告的错误很奇怪,我看不到 mcar 的使用位置 - 或可变状态。试试这个设置,它适用于我,无需使用 Neil Van Dyke 的支持语言:

    #lang racket
    
    (define the-empty-stream '())
    
    (define (stream-null? stream)
      (null? stream))
    
    (define-syntax cons-stream
      (syntax-rules ()
        ((cons-stream head tail)
         (cons head (delay tail)))))
    
    (define (stream-car stream)
      (car stream))
    
    (define (stream-cdr stream)
      (force (cdr stream)))
    
    ; ... the rest is the same as in your question
    

    【讨论】:

    • 感谢您的回答。但奇怪的是,当我使用此设置运行相同的命令(stream-ref (solve (lambda (y) y) 1 0.001) 1000) 时,我也会收到错误消息:force: reentrant promise |...mentos\sicp\3-77.rkt:14:16|。显然,这发生在执行stream-cdr 的阶段。
    • 更改语言,而不是 SICP 选择“从源代码确定语言”并重试
    • 我之前更改了语言,但我一定是做错了什么。我又试了一次,现在它起作用了。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    • 2011-04-17
    • 1970-01-01
    相关资源
    最近更新 更多