3
votes

I'm having trouble running an example code from SICP (Structure and Interpretation of Computer Programs) Section 3.5.4 (Streams and Delayed Evaluation); the SICP section can be found here: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-24.html#%_sec_3.5.4.

I'm using DrRacket version 5.2.1, set up with the SICP support language by Neil Van Dyke (SICP PLaneT 1.17), which can be found here: http://www.neilvandyke.org/racket-sicp/#%28part._installation%29.

The code, shown below, makes use of streams. With the environment set up as above, the procedures cons-stream, force and delay are already available from DrRacket. But stream-car and stream-cdr weren't available; so, I had to define them. In the code below, I also define some generic stream functions: stream-map, stream-ref, add-streams and scale-stream.

The whole code I'm trying to make work is the following. It includes a procedure to solve first-order differential equations numerically (solve), using an integration procedure (integral), which uses a delayed argument (delayed-integrand); these procedures come from Section 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)

When I put the definitions above in DrRacket and click Run, no error occurs. However, an error occurs when I try to execute the following line in the interactions window:

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

The error message is:

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

When this error occurs, DrRacket highlights the body of the definition of the procedure stream-car, as shown in the picture below:

DrRacket error


What is causing this error? I have already used the stream procedures above in previous examples (stream-car, stream-cdr, stream-map, add-streams and scale-stream) and they worked. The integral procedure also works when I use it outside of the solve procedure; for example, if I define (define ones (cons-stream 1 ones)) and then I define (define s (integral (delay ones) 1 1)) and then I execute (stream-ref s 1000), it correctly gives the output 1001.

1

1 Answers

5
votes

The error you're reporting is rather weird, I can't see where mcar is being used - or mutable state for that matter. Try this setup, it works for me without using Neil Van Dyke's support language:

#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