Exercise #7

Let's consider still another way to represent sequences in Scheme: We can implement a sequence as an object with internal state, an object that processes messages that are transmitted to it (as arguments).

In particular, our ``sequence objects'' should respond to four messages, represented by the four symbols at-end?, next, so-far, and reset.

The idea is that we can advance through a given sequence by repeatedly sending it the next message, which should cause the object to generate and return the next element of the sequence.

The object should respond to the at-end? message by returning a Boolean value indicating whether it can generate another element. If so, the object should return #t; if not -- that is, if all of the elements of the sequence have been returned in previous calls to next -- the object should return #f.

Sending the object the reset message should cause it to start over at the beginning of the sequence (so that it responds to the next next message with the first element of the sequence). The value that the object returns when it receives the reset message is unspecified; in other words, it could be anything, and programmers who send this message should not try to extract any information from that return value.

Finally, when the object receives a so-far message, it returns the number of elements that it has generated and returned since receiving the last reset message (or since it was created, if it has never received a reset message).

It is an error to send a sequence object the next message when it cannot generate any more elements (that is, when it would respond to the at-end? message with #t). It is also an error to send any message other than one of these four to a sequence object.

To illustrate these ideas, here is the definition for an object one-to-four that represents the finite sequence of integers from 1 to 4:

(define one-to-four
  (let ((next-element 1))
    (lambda (message)
      (cond ((eq? message 'at-end?) (< 4 next-element))

            ((eq? message 'next)
             (if (< 4 next-element)
                 (error "NEXT: ONE-TO-FOUR has no more elements.")
                 (let ((current next-element))
                   (set! next-element (+ next-element 1))
                   current)))

            ((eq? message 'reset) (set! next-element 1))

            ((eq? message 'so-far) (- next-element 1))

            (else (error (string-append "ONE-TO-FOUR: "
                           (symbol->string message)
                           " is not a recognized sequence message.")))))))

And here is the transcript of some interactions with the one-to-four object:

> (one-to-four 'next)
1
> (one-to-four 'next)
2
> (one-to-four 'at-end?)
#f
> (one-to-four 'so-far)
2
> (one-to-four 'reset)
> (one-to-four 'next)
1
> (one-to-four 'clear)
[bug] ONE-TO-FOUR: clear is not a recognized sequence message.
> (one-to-four 'next)
2
> (one-to-four 'next)
3
> (one-to-four 'so-far)
3
> (one-to-four 'next)
4
> (one-to-four 'at-end?)
#t
> (one-to-four 'next)
[bug] NEXT: ONE-TO-FOUR has no more elements.

Part (a)

Define and test an object that represents the infinite sequence of squares of non-negative integers (0, 1, 4, 9, 16, ...).

Part (b)

Define and test an object that represents the empty sequence (which has no elements).

Part (c)

Define and test a list->sequence-object procedure that takes any list as argument and returns a sequence object whose successive elements are the successive elements of the list.

Part (d)

Define and test a sequence-object->list procedure that takes as argument any sequence object that represents a finite sequence and returns a list of the elements of the sequence it represents (in the same order).

Part (e)

Define and test a sequence-object-cumulate procedure that takes any sequence object as its argument and returns another sequence object, one that represents the sequence of cumulative sums of elements of the given sequence object.

This exercise will be due at 9 a.m. on Monday, April 5.


This document is available on the World Wide Web as

http://www.cs.grinnell.edu/~stone/courses/scheme/exercises/7.xhtml

Validated as XHTML 1.1 by the World Wide Web Consortium Cascading Style Sheet validated by the World Wide Web Consortium

created March 26, 2004
last revised March 26, 2004

John David Stone (stone@cs.grinnell.edu)