rwaldhoff 2003/03/31 10:21:52 Modified: functor/xdocs examples.xml functor/src/test/org/apache/commons/functor/example QuicksortExample.java Log: minor changes to examples Revision Changes Path 1.3 +6 -4 jakarta-commons-sandbox/functor/xdocs/examples.xml Index: examples.xml =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/functor/xdocs/examples.xml,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- examples.xml 12 Mar 2003 21:08:16 -0000 1.2 +++ examples.xml 31 Mar 2003 18:21:52 -0000 1.3 @@ -80,15 +80,17 @@ </p> <p> The - <a href="xref-test/org/apache/commons/functor/example/FlexiMapExample.html#88">FlexiMap</a> - example applies this design to <code>java.util.Map</code>, demonstrating how + <a href="xref-test/org/apache/commons/functor/example/FlexiMapExample.html#88">FlexiMap example</a> + applies this design to <code>java.util.Map</code>, demonstrating how "pluggable" functors can be applied to a generic <code>Map</code> structure in order to introduce new behaviors. </p> </subsection> - <subsection name="A Functional Quicksort Implementation"> + <subsection name="A Quicksort Implementation"> <p> - See the <a href="xref-test/org/apache/commons/functor/example/QuicksortExample.html#79">Quicksort</a> example. + The <a href="xref-test/org/apache/commons/functor/example/QuicksortExample.html#79">Quicksort example</a> + presents an implementation of the Quicksort sorting algorithm written in a functional programming + style using Commons Functor. </p> </subsection> </section> 1.3 +160 -51 jakarta-commons-sandbox/functor/src/test/org/apache/commons/functor/example/QuicksortExample.java Index: QuicksortExample.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/functor/src/test/org/apache/commons/functor/example/QuicksortExample.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- QuicksortExample.java 12 Mar 2003 21:08:16 -0000 1.2 +++ QuicksortExample.java 31 Mar 2003 18:21:52 -0000 1.3 @@ -342,13 +342,92 @@ System.out.println(); } + /* - * BUILDING BLOCKS: + * THE QUICKSORT ALGORITHM: * ---------------------------------------------------------------------------- + */ + +/* + * Our quicksort method will invoke a UnaryFunction named + * quicksort: + */ + + public List quicksort(List list) { + return (List)(quicksort.evaluate(list)); + } + +/* + * The quicksort sorting algorithm can be summarized as follows: + * + * Given a list of elements to be sorted: + * + * A) If the list is empty, consider it already sorted. + * + * B) If the list is non-empty, we can sort it by first splitting it into + * three lists: + * 1) one list containing only the first element in the list (the "head") + * 2) one (possibly empty) list containing every element in the remaining + * list that is less than the head + * 3) one (possibly empty) list containing every element in the remaining + * list that is greater than or equal to the head + * applying the quicksort algorithm recursively to the second and third lists, + * and joining the results back together as (2) + (1) + (3). + */ + +/* + * Using a functional style (or at least a semi-functional style), it's easy + * to transalate this description directly into code: + */ + + private UnaryFunction quicksort = new ConditionalUnaryFunction( + /* if the list is empty... */ + IsEmpty.getIsEmpty(), + /* ...then return an empty list... */ + new ConstantFunction(Collections.EMPTY_LIST), + /* ...else, apply the following function... */ + new ListFunction() { + public Object evaluate(List list) { + /* Create a list to contain the results. */ + List result = new ArrayList(list.size()); + /* + * Recursively apply quicksort the the elements in the + * tail less than the head, adding the result to the + * sorted list we're generating. + */ + result.addAll( + (List)quicksort.evaluate( + lesserTail.evaluate( + head.evaluate(list), + tail.evaluate(list)))); + /* + * Add the head to the sorted list we're generating. + */ + result.add(head.evaluate(list)); + /* + * Recursively apply quicksort the the elements in the + * tail greater than the head, adding the result to the + * sorted list we're generating. + */ + result.addAll( + (List)quicksort.evaluate( + greaterTail.evaluate( + head.evaluate(list), + tail.evaluate(list)))); + /* + * And return the generated list. + */ + return result; + } + }); + +/* + * Now let's look at the building blocks we need to flesh out that + * function. + * + * First, let's save ourselves some casting and error handling by + * definining some functor sub-types. * - * Let's save ourselves some casting and error checking by defining - * functor subclasses that deal with java.util.List. - * * Let ListFunction be a UnaryFunction that operates on Lists: */ @@ -372,7 +451,7 @@ * Let ObjectListFunction be a BinaryFunction that operates on * an Object, List pair: */ - + public abstract class ObjectListFunction implements BinaryFunction { public abstract Object evaluate(Object head, List tail); @@ -391,30 +470,8 @@ } } -/* - * THE QUICKSORT ALGORITHM: - * ---------------------------------------------------------------------------- - * - * The quicksort sorting algorithm can be summarized as follows: - * - * Given a list of elements to be sorted: - * - * A) If the list is empty, consider it already sorted. - * - * B) If the list is non-empty, we can sort it by first splitting it into - * three lists: - * 1) one list containing only the first element in the list (the "head") - * 2) one (possibly empty) list containing every element in the remaining - * list that is less than the head - * 3) one (possibly empty) list containing every element in the remaining - * list that is greater than or equal to the head - * applying the quicksort algorithm recursively to the second and third lists, - * and joining the results back together as (2) + (1) + (3). - * - */ - /* - * Let's define functors for the operations we'll need. + * Now for the implementations. * * Given a List, we need to be able to break it into its head: */ @@ -467,29 +524,81 @@ } }; -/* - * With these building blocks, our quicksort function is a - * straightfoward application of the description above. +/* + * Note that each of these smaller functors is readily testable + * in isolation: */ - private UnaryFunction quicksort = new ConditionalUnaryFunction( - IsEmpty.getIsEmpty(), /* If the list is empty, */ - new ConstantFunction(Collections.EMPTY_LIST), /* then return an empty list, */ - new ListFunction() { /* else, split and recurse */ - public Object evaluate(List list) { - List result = new ArrayList(list.size()); - Object h = head.evaluate(list); - Object t = tail.evaluate(list); - result.addAll((List)quicksort.evaluate(lesserTail.evaluate(h, t))); - result.add(h); - result.addAll((List)quicksort.evaluate(greaterTail.evaluate(h, t))); - return result; + + public void testHeadFunction() { + List list = new ArrayList(); + try { + head.evaluate(list); + fail("Expected IndexOutOfBoundsException when evaluating head of an empty list"); + } catch(IndexOutOfBoundsException e) { + // expected } - }); + + list.add("First"); + assertEquals("First",head.evaluate(list)); + + list.add("Second"); + assertEquals("First",head.evaluate(list)); + + } + + public void testTailFunction() { + List list = new ArrayList(); + { + List result = (List)(tail.evaluate(list)); + assertTrue("Tail of an empty list is empty.",result.isEmpty()); + } + list.add("First"); + { + List result = (List)(tail.evaluate(list)); + assertTrue("Tail of a one element list is empty.",result.isEmpty()); + } + list.add("Second"); + { + List result = (List)(tail.evaluate(list)); + assertEquals("Tail of a two element list has one element.",1,result.size()); + assertEquals("Second",result.get(0)); + } + list.add("Third"); + { + List result = (List)(tail.evaluate(list)); + assertEquals("Tail of a three element list has two elements.",2,result.size()); + assertEquals("Second",result.get(0)); + assertEquals("Third",result.get(1)); + } + } -/* - * Finally, our quicksort method simply invokes the UnaryFunction: - */ - public List quicksort(List list) { - return (List)(quicksort.evaluate(list)); + public void testLesserTail() { + List list = new ArrayList(); + for(int i=0;i<10;i++) { + list.add(new Integer(i)); + } + for(int i=0;i<10;i++) { + Integer val = new Integer(i); + List lesser = (List)lesserTail.evaluate(val,list); + assertEquals(i,lesser.size()); + for(int j=0;j<i;j++) { + assertEquals(new Integer(j),lesser.get(j)); + } + } + } + + public void testGreaterTail() { + List list = new ArrayList(); + for(int i=0;i<10;i++) { + list.add(new Integer(i)); + } + for(int i=0;i<10;i++) { + Integer val = new Integer(i); + List greater = (List)greaterTail.evaluate(val,list); + assertEquals(10-i,greater.size()); + for(int j=i;j<10;j++) { + assertEquals(new Integer(j),greater.get(j-i)); + } + } } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]