|CSC 153||Grinnell College||Spring, 2005|
|Computer Science Fundamentals|
This laboratory exercise reviews strategies of problem solving discussed in this class. Then, building on recent work, the lab introduces stacks and queues as examples of useful classes.
The reading for this laboratory exercise outlines several strategies and language capabilities for handling complexity. These include the use of procedures, local variables, parameters, recursion, data abstraction, procedural abstraction, libraries, and classes and objects.
The reading describes a stack as an object that contains can store data and that has the following operations:
To implement a class within Scheme, we may proceed following the recent reading on Abstract Data Types. The simplest approach is to maintain an internal list within the abstract data type or class. With this approach, push and pop operations insert or delete an item from the front of the list, the empty operation tests if the list is empty, and the top operation returns the head of the list.
> (define mag-pile ... ) ; make stack for magazines ; (details of call dependent on implementation) > (define bill-pile ... ) ; make stack for bills ; (details of call dependent on implementation) > (bill-pile 'push! "mortgage") ; send push message to bill-pile > (bill-pile 'push! "doctor's bill") > (bill-pile 'push! "credit card") > (bill-pile 'empty?) ; send empty? message to bill-pile #f ; response from empty? message > (mag-pile 'empty?) #t > (mag-pile 'push! "Communications of the ACM - April 1997") > (mag-pile 'push! "CS Education Bulletin - Spring 1998") > (bill-pile 'top) ; send top message to bill-pile "credit card" ; data returned as message response > (mag-pile 'top) "CS Education Bulletin - Spring 1988" > (bill-pile 'pop!) "credit card" > (bill-pile 'top) "doctor's bill"
A queue class may be defined with the following constructor for creating new objects:
(define queue-class (lambda () (let* ((front (list 'dummy-header)) (rear front)) (lambda (message . arguments) (case message ((empty?) (null? (cdr front))) ((enqueue!) (if (null? arguments) (error 'queue-class "method ENQUEUE!: An argument is required") (begin ; Attach a new cons cell behind the current rear ; element. (set-cdr! rear (list (car arguments))) ; Advance REAR so that it is once more a list ; containing only the last element. (set! rear (cdr rear))))) ((dequeue!) (if (null? (cdr front)) (error 'queue-class "method DEQUEUE!: The queue is empty") ; Recover the first element of the queue (not including ; the dummy header). (let ((removed (cadr front))) ; Splice out the element to be dequeued. (set-cdr! front (cddr front)) ; If you just spliced out the last element of the ; queue, reset REAR so that it holds the dummy ; header. (if (null? (cdr front)) (set! rear front)) removed))) ((front) (if (null? (cdr front)) (error 'queue "method FRONT: The queue is empty") (cadr front))) (else (error 'queue-class "unrecognized message")))))))
Add to the queue an additional method, activated by the
Write a procedure
print-symbols that creates an empty queue,
then processes a list to put each symbol on the list or on any sublist into
the queue, and finally uses the
(print-symbols '(((to) be) (or (not (to ((be)))))))should print
to be or not to be
Rewrite the previous
print-symbols procedure to use a stack
instead of a queue to store the symbols. How does the output differ from
that obtained in the previous problem?
This document is available on the World Wide Web as
created April 28, 1997
last revised March 15, 2005
|For more information, please contact Henry M. Walker at firstname.lastname@example.org.|