CS 217: Programming Languages

Programming Assignment 3: Java

Assigned on Friday, Feb 7.
Due at 5 PM on Wednesday, Feb 19.


Use hsp to turn in an entire directory called java that contains the files Prog1.java, Prog2.java, and LazyList.java. If you need to resubmit your homework, resubmit the entire directory with an underscore and a version number. For example, if I need to resubmit my java directory, I would name it java_2 (for version 2).

Warmup

Work through the Java introductory lab. This is intended to be easy and quick, and designed to be a warmup to get you started in Java if you are new to the language. Turn in Prog1 and Prog2 from the lab when done.

The main act

Your task: Redo the last problem of the ML assignment (lazy lists and the "Sieve of Eratosthenes") in Java. Since Java is not polymorphic, you'll need to implement lazy lists of type Object. Since Java does not support first-class functions, you'll need to use the following "trick" to encapsulate a function within a class definition. Suppose that we wish to pass a function of type () -> LazyList. We'll first create an abstract class that contains only one member function, f:

abstract class LazyListFct {
  abstract LazyList f();
}

All subclasses of LazyListFct will simply redefine f to be a particular () -> LazyList function. For example, here is an excerpt from the infSeq function that you will write:

class LazyList {
  ...
  public static LazyList infSeq(final int start) { 

    class InfSeqTail extends LazyListFct {
      LazyList f() {
        return infSeq(start+1);
      }
    } // end of inner-class definition

    // The code for infSeq goes here, using the above class
    ...
  }
  ...
}

Whenever a particular function must be passed as a value, an instance of a subclass of LazyListFct is used. The class you need to implement, LazyList, is structured as:

class LazyList {
  private Object head;       // Head of this list, null if list is empty
  private LazyListFct tail;  // Function to compute tail of this list
                             // (if head is not null)
  public LazyList() {        // Default constructor for LazyList
    head = null;
  }
  public LazyList(Object head, LazyListFct tail) {
    // Another constructor
    this.head = head;
    this.tail = tail;
  }
  public static LazyList seq(final int start, final int finish) {
    // Same definition as in SML assignment
  }
  public static LazyList infSeq(final int start) {
    // Same definition as in SML assignment
  }
  public Object Nth(int n) {
    // Same definition as in SML assignment
    // EXCEPT that it returns null if if n-th element does not exist
  }
  public void printN(int n) {
    // Like firstN except that values are printed
    // rather than formed into a list.
  }
  public static LazyList filterMultiples(final int factor,
                                         final LazyList data) {
    // Same definition as in SML assignment
  }
  public static LazyList primes() {
    // Same definition as in SML assignment
  }

  public static void main(String[] args) {
    // Create a lazy list and test that it works
    LazyList primes = LazyList.primes();
    primes.printN(15);
    System.out.println(primes.Nth(20));
  }

}

I am indebted to Charles Fischer at University of Wisconsin-Madison for writing the LazyList problem.