// file: examples.C // author: Robert Keller // purpose: Examples of using the Polya C++ library // compile: g++ examples.C polya.o // See polya.html for documentation. #include "polya.H" #include #include // forward prototypes Poly square(Poly x); Poly scale(Poly k); Poly list2(Poly a, Poly b); Poly isOdd(Poly x); Poly greaterThan5(Poly x); Poly list2(Poly a, Poly b); Poly precat(Poly x); Poly upto(Poly n); Poly applyto(Poly f); Poly addTag(Poly a); // Making an Oclosure for a Curried add functoin class occ1 : public Applicable { private: Poly arg1; public: occ1(Poly arg1) // constructor { this->arg1 = arg1; } Poly operator()(Poly arg2) const // applier { return cat(arg1, arg2); } }; void examples() { cout << "Three ways of getting the empty list: " << nil << NIL << list() << endl; cout << "Constructing a list by enumerating its elements: " << list(1, 2, 3) << endl; cout << "Constructing a heterogenous list: " << list(1, 2, "buckle", "my", "shoe") << endl; cout << "Setting a variable to a list: "; Polylist L = list(1, 2, 3); cout << L << endl; cout << "Constructing a list using cons: " << cons(0, L) << endl; cout << "Constructing a list with lists as elements: " << "list of lists: " << list(list(1, 2, 3), list(4, 5), list(6)) << endl; cout << "Reversing a list (non-destructively): " << L.reverse() << endl; cout << "Using functional syntax: " << reverse(L) << endl; cout << "Appending one list to another (non-destructively): "; Polylist M = list("x", "y", "z"); cout << L.append(M) << endl; cout << "Appending using ^ operator: "; cout << (L ^ M ^ L) << endl; cout << "Generating a range list: "; L = range(0, 9); cout << L << endl; cout << "Using word selectors: " << first(L) << second(L) << third(L) << fourth(L) << fifth(L) << sixth(L) << seventh(L) << eighth(L) << ninth(L) << tenth(L) << endl; cout << "Using rest: " << L.rest() << endl; cout << "Using numeric selectors, length: " << L[0] << L[1] << L[2] << L[3] << L[4] << L[L.length()-1] << endl; cout << "Testing membership: " << member(5, L) << member(10, L) << endl; cout << "Prefixing: " << L.prefix(5) << endl; cout << "Mapping: " << L.map(square) << endl; cout << "Keeping odd: " << L.keep(isOdd) << endl; cout << "Dropping odd: " << L.drop(isOdd) << endl; cout << "Finding > 5: " << L.find(greaterThan5) << endl; cout << "Association list: "; Polylist alist = list(list("a", "alpha"), list("e", "epsilon"), list("i", "iota"), list("o", "omicron"), list("u", "upsilon")); cout << alist.assoc("o") << alist.assoc("z") << endl; cout << "Reducing a list by 'folding': " << endl; Polylist args = list("a1", "a2", "a3", "a4", "a5", "a6", "a7"); cout << " foldl: " << args.foldl(list2, "unit") << endl << " foldr: " << args.foldr(list2, "unit") << endl; // user-defined list2 is used because list is overloaded and would be ambiguous cout << "Accumulated reduction using scan operators:" << endl << " scanl: " << L.scanl(cat, "") << endl << " scanr: " << L.scanr(cat, "") << endl; cout << "Imploding a list to a string: " << L.implode() << endl; cout << "Reading characters from a file: " << endl; ifstream input("test.in"); cout << Polylist::inchars(input).implode() << endl; cout << "The empty array: " << array() << endl; cout << "An array with specific elements: " << array(1, 2, 3, "foo", "bar") << endl; cout << "Setting an array variable: "; Polyarray A = array(1, 2, 3, "foo", "bar"); cout << A << endl; cout << "Setting array elements from a list: "; A = L; cout << A << endl; cout << "Mapping over an array: " << A.map(square) << endl; cout << "Indexing an array, length of an array: " << A[0] << A[A.length()-1] << endl; cout << "Mapping using a higher-order function (scale): " << endl; cout << " scaled by 2: " << L.map(scale(2)) << endl; cout << " scaled by 3: " << A.map(scale(3)) << endl; cout << "Printing a function closure: " << scale(2) << endl; cout << "Reversing array in place: "; A.reverse(); cout << A << endl; cout << "Sorting array in place: "; A.sort(); cout << A << endl; cout << "Resizing array in place: " << endl; A.resize(5); cout << A << endl; A.resize(10); cout << A << endl; cout << "Making arrays and lists using a function: " << endl << Polylist::make(square, 10) << endl << Polyarray::make(square, 10) << endl; cout << "Testing for equality, etc.: " << endl; cout << "These should give 0: " << (list(1, 2, 3) == list(3, 2, 1)) << (array(1, 2, 3) < array(1, 2, 3)) << (list(1, 2, 3) < list(1, 2, 3)) << endl; cout << "These should give 1: " << (nil == array()) << (list(1, 2, 3) == array(1, 2, 3)) << (list(1, 2, 3) < list(2, 3, 4)) << (array(1, 2, 3) < list(1, 2, 4)) << (array(1, 2, 3) < list(2, 2, 3, 4)) << endl; cout << "Expanding an infinite list incrementally: "; Polylist Ints = Polylist::from(0); cout << Ints << endl; Ints.prefix(10); cout << "After expanding: " << Ints << endl; cout << "Appending an infinite list to a finite one: " << endl << range(-10, -1).append(Ints) << endl; cout << "Mapping conversion functions: " << endl; Polylist Floats = range(0.5, 9.5); cout << Floats.map(makeInteger) << endl; cout << Floats.map(precat("x"))<< endl; cout << "Some random integers in the range 0 to 99: " << endl; Polylist random = Polylist::random(0, 100); cout << random.prefix(20) << endl; cout << "Modifying list structure: " << endl; Polylist X = list(1, 2, 3); X.rest().rest().rawRest() = list(4, 5, 6); cout << X << endl; cout << "Adding number to string, similar to Java" << endl; cout << Poly("foo") + Poly(1234) + Poly("bar") << endl; cout << "Appending one array to another (non-destructively): "; A = range(0, 5); Polyarray B = range(6, 9); cout << A.append(B) << endl; cout << "Appending arrays using ^ operator: "; cout << (A ^ B ^ A) << endl; cout << "Analyzing file input using deepType(): " << endl; Poly p; ifstream input2("test.in"); while( input2 >> p ) { cout << "entered: " << p << endl; cout << "deepType: " << p.deepType() << endl; } cout << endl; cout << "Using mappend: " << range(0, 5).mappend(upto) << endl; cout << "mappend on infinite sequence: " << from(0).mappend(upto).prefix(20) << endl; cout << Polylist(append(from(0), from(0))).prefix(20) << endl; cout << Polylist(range(0, 5).map(upto).foldl(append, nil)).prefix(20) << endl; cout << Polylist(range(0, 5).map(upto)).prefix(20) << endl; Oclosure Oc1(new occ1("hello,")); cout << "Testing Oclosure: " << Oc1("world") << endl; Oclosure Oc2 = Oc1; cout << "Testing Oclosure: " << Oc2("goodbye") << endl; cout << "Testing sequence of functions: "; Polylist fns = map(precat, range(1, 5)); cout << map(applyto(", "), fns) << endl; cout << "Testing sequence of oclosures: "; Polylist ocs = map(addTag, range(1, 5)); cout << map(applyto("x"), ocs) << endl; } // Various functions used in examples // squaring function Poly square(Poly x) { floating z = x; return z*z; } // Function2 for use with closure in scale Poly scaler(Poly k, Poly x) { return k*x; } // scaling function (higher-order) Poly scale(Poly k) { return Fclosure(scaler, k); } // odd-testing predicate Poly isOdd(Poly x) { return integer(x) % 2 == 1; } // floating-testing predicate Poly isFLOATING(Poly x) { return isFloating(x); } // predicate testing > 5 Poly greaterThan5(Poly x) { return integer(x) > 5; } // predicate making list of 2 elements // (plain list of 2 args is too overloaded) Poly list2(Poly a, Poly b) { return list(a, b); } // precat returns a function which concatenates a given string argument // to its argument. // precatFun is the closure function used by precat Poly precatFun(Poly x, Poly y) { return cat(x, y); } Poly precat(Poly x) { return Fclosure(precatFun, x); } // upto(n) makes a list (0 .... n) Poly upto(Poly n) { return range(0, n); } Poly applier(Poly a, Poly f) { return f.operator()(a); } // applyto(a) returns a function which, when applied to a function f, // returns f(a). Poly applyto(Poly a) { return Fclosure(applier, a); } // addTag returns a function which adds a tag a to its argument Poly addTag(Poly a) { return Oclosure(new occ1(a)); } main() { examples(); Poly::report(); }