/** * Represents an abstract Scheme-like list, an immutable linear recursive * structure of data. Has abstract methods to provide its internal data and * structure to the client. Since an AList has an internal structure that is * isomorphic to itself, it's best to implement it using the composite pattern. */ public abstract class AList { /** * Computes the minimum of this AList, assuming it contains Integer objects. * Uses helpGetMin. * @return behavior relegated to concrete subclasses. */ public abstract int getMin(); /** * Computes the minimum of the preceding list and this AList using the * accumulated minimum. * @param accMin the smallest int containing in the list preceding this AList. * @return behavior relegated to concrete subclasses. */ protected abstract int helpGetMin(int accMin);
/** * If this AList is empty, returns the empty list, else returns an AList * consisting of the even-indexed elements of this AList, with 0 being the * index of the first element of a non-empty list. Uses helpEveryOther(). * @return behavior relegated to concrete subclasses. */ public abstract AList everyOther(); /** * Accepts as input the first element of the enclosing list and builds an * AList consisting of every other element of the enclosing list. * @param first the first element of the enclosing list. * @return behavior relegated to concrete subclasses. */ protected abstract AList helpEveryOther(Object first);
/** * Computes the length of this AList. Uses helpGetLen. * @return int >= 0. */ public abstract int getLen(); /** * Uses the accumulated length of the preceding list to help compute the * length of the preceding list. * @param acc the accumlated length of the preceding list. * @return behavior relegated to concrete subclasses. */ protected abstract int helpGetLen(int acc); // Other methods elided ... }
public class
EmptyList extends AList { public final static EmptyList Singleton = new EmptyList(); private EmptyList() { } |
public class
NEList extends AList { private Object _first; private AList _rest; |
/** |
/** * Asks _rest for help to compute the min, passing it * the int value of _first as the accumulated min. * @return the minimum int contained in this NEList. */ public int getMin() { return _rest.helpGetMin(((Integer)_first).intValue()); } |
/** * Returns the accumulated minimum, since this is the end of the list. * @param accMin the smallest int containing in the list preceding this NEList. * @return accMin. */ protected int helpGetMin(int accMin) { return accMin; } |
/** * Computes the smaller of the accumulated min parameter * and the value of _first, and passes the result down to the * tail for help to compute the min. * @param accMin the smallest int containing in the list preceding this NEList. * @return the minimum int contained in the preceding list and this NEList. */ protected int helpGetMin(int accMin) { return _rest.helpGetMin(Math.min(((Integer)_first).intValue(), accMin)); } |
/** * The empty list contains all even-indexed elements of the empty list! * @return this */ public AList everyOther() { return this; } |
/** * Passes _first to _rest, asking it for help to collect every other * elements and builds the resulting list. * @return an AList consisting of every other elements of this AList. */ public AList everyOther() { return _rest.helpEveryOther(_first); } |
/** * The enclosing list has an empty tail. This means the enclosing list has * only one element. * @param first the first element of the enclosing list. * @return a NEList with fist as its only element. */ protected AList helpEveryOther(Object first) { return new NEList( first, this); } |
/** * "Cons" the parameter first the the list consisting of every other * elements of _rest. * @param first the first element of the enclosing list. * @return an AList consisting of every other elements of the enclosing list. */ protected AList helpEveryOther(Object first) { return new NEList(first, _rest.everyOther()); } |
/** * Computes the length of this EmptyList. * @return 0. */ public int getLen() { return 0; } |
/** * Asks the tail for help to compute the length, passing * it an accumulated length of 1, and returns the result. */ public int getLen() { return _rest.helpGetLen(1); } |
/** * Returns the accumulated length, since this is the end of the list. * @param acc the length of the list preceding this EmptyList. * @return acc. */ protected int helpGetLen(int acc) { return acc; } } |
/** * Adds 1 to the accumulated length, passes it down to the * tail for help to compute the length, and returns the result. * @param acc the length of the list preceding this NEList. * @return int > acc. */ protected int helpGetLen(int acc) { return _rest.helpGetLen(acc + 1); } } |