import geometry.*; import tester.*; // Filtering based on predicates. interface IPred { boolean apply(T t); } // Posn predicate: x coord equals y coord? class PosnSameXY implements IPred { PosnSameXY() {} // Is the given posn's x and y the same? public boolean apply(Posn p) { return p.x == p.y; } } // Posn predicate: on screen? class PosnOnScreen implements IPred { PosnOnScreen() {} // Is the given posn on the screen? public boolean apply(Posn p) { return 0 <= p.x && p.x <= 10 && 0 <= p.y && p.y <= 10; } } interface IList { // Filter this list keeping those that satisfy pred. IList filter(IPred p); } class MT implements IList { MT() {} // Filter this empty list keeping those that satisfy pred. public IList filter(IPred p) { return this; } } class Cons implements IList { T first; IList rest; Cons(T first, IList rest) { this.first = first; this.rest = rest; } // Filter this cons list keeping those that satisfy pred. public IList filter(IPred p) { if (p.apply(this.first)) return new Cons(this.first, this.rest.filter(p)); else return this.rest.filter(p); } } class Examples { Examples() {} Posn p1 = new Posn(3,4); Posn p2 = new Posn(11,11); Posn p3 = new Posn(2,2); // List of Posns with same x, y coordinate IList same = new Cons(this.p2, new Cons(this.p3, new MT())); // List of Posns on the screen IList scrn = new Cons(this.p1, new Cons(this.p3, new MT())); // List of Posns with same x, y coordinate AND on the screen IList sameScreen = new Cons(this.p3, new MT()); // All of the Posns IList all = new Cons(this.p1, this.same); boolean testFilter(Tester t) { return t.checkExpect(this.all.filter(new PosnSameXY()), this.same) && t.checkExpect(this.all.filter(new PosnOnScreen()), this.scrn) && t.checkExpect(this.all.filter(new PosnSameXY()) .filter(new PosnOnScreen()), this.sameScreen); } }