COS 371: Programming Languages

Spring 2022

hw3: Lazy lists

Due: Wednesday, 02/16 at 22:00

This is a solo/pair programming assignment. You may either work alone or with one other student of your choice. If you are pair programming, this means that you and your partner should be doing the entirety of this assignment side-by-side, on a single computer, where one person is "driving" and the other is "navigating." (Or a remote equivalent of this experience.) Set a timer to swap every 15 minutes, say. You can choose your favourite from this online timer page. You are not allowed to divide-and-conquer the assignment by each working separately on half of it. If your schedule does not allow you to find enough time to meet together to complete the entire assignment side-by-side, you should opt to do the assignment solo instead.

1. Goals

To build a data structure to represent a (possibly infinite) sequence of elements.

2. Introduction

Try the following in Python 2
range(3,23)
xrange(3,23)
for n in xrange(3,23):
   print n
and the following in Python 3
range(3,23)
for n in range(3,23):
   print(n)
It would seem that xrange in Python 2 and range in Python 3 yield some kind of (relatively small) objects that represent (possibly large) sequences of numbers. The actual sequence does not need to be generated until needed. Think about difference in storage requirements when the 23 above are replaced with, say, 23000000000000. (If you want to learn more, read about iterators and generators in Python.)

We now try to do this in Scheme. Recall that a nonempty list in Scheme consists of two parts:

Analogously, a nonempty lazy list in Scheme consists of two parts: where the thunk is a zero-parameter function that, when called, returns a lazy list.

The key is that the body of a function in Scheme is not evaluated until the function is called, so infinite recursion does not appear to be a problem.

The Scheme function (range a b) generates a list of integers from a up to and including b, like range(a,b+1) in Python 2.

(define range
  (lambda (a b)
    (if (> a b)
        '()
        (cons a
              (range (+ a 1) b)))))
Compare this with (lazy-range a b), which generates a lazy range, like xrange(a,b+1) in Python 2 or range(a,b+1) in Python 3.
(define lazy-range
  (lambda (a b)
    (if (> a b)
        '()
        (cons a
              (lambda () (lazy-range (+ a 1) b))))))
The result of (lazy-range a b) is a cons cell, whose car is is the first integer; and whose cdr is a zero-parameter function that, when called, returns the rest of the sequence represented as a pair of the same (lazy) structure.

We still use the empty list () to represent an empty lazy list.

3. Specification

4. Notes

5. Optional Challenges

6. Submission

Submit your code in a file called lazy-list.scm.

Start early, have fun, and discuss questions on Moodle.