Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

OpenList.java

Go to the documentation of this file.
00001 // file:    OpenList.java
00002 // author:  Robert M. Keller
00003 // purpose: Implement Open Lists is java
00004 
00005 import OpenListException;
00006 
00007 /**
00008  * OpenList is a type of uni-directional linked list that permits sharing
00009  * of list tails.  It is similar to the list representation used in many 
00010  * functional languages, such as rex, Lisp, etc.
00011  */
00012 
00013 class OpenList
00014 {
00015 /** 
00016  the default left paren used when a list is printed. 
00017  Defaults are used when the toString() method is called, i.e. whenever
00018  an OpenList is automatically cast to a String, as in printing.
00019  To use different punctuation, or no punctuation, use the three-argument
00020  toString, and supply the punctuation you want.
00021 */
00022 
00023 public static String defaultLeftParen = "[";
00024 
00025 
00026 /** the default right paren used when a list is printed */
00027 
00028 public static String defaultRightParen = "]";
00029 
00030 
00031 /** the default space used when a list is printed */
00032 
00033 public static String defaultSpacer = ", ";
00034 
00035 
00036 /** 
00037  * the one and only empty OpenList.  Do not create any others.
00038  * This list is represented by a unique cell allocated for the purpose.
00039  * The first and rest are not intended to be used.  We do not use null
00040  * for this list, so that we can call methods on it.
00041  */
00042 
00043 final public static OpenList nil = cons(null, null);
00044 
00045 
00046 /** exception message for first of empty list */
00047 
00048 public static String firstOfOpenListException = "first() of empty list";
00049 
00050 
00051 /** exception message for rest of empty list */
00052 
00053 public static String restOfOpenListException = "rest() of empty list";
00054 
00055 
00056 /** the Object in the first cell of a non-empty list */
00057 
00058 private Object First;
00059 
00060 
00061 /** the rest of a list, defined to be an OpenList of all but the first cell */
00062 
00063 private OpenList Rest;  
00064 
00065 /** 
00066  * Construct an OpenList from its first and rest.
00067  * This constructor is private because it is intended that the 
00068  * pseudo-constructor (or "factor") cons be used outside.
00069  *
00070  * @param _First the first Object in the list
00071  * @param _Rest list of the rest of the objects in the list
00072  */
00073 
00074 private OpenList(Object _First, OpenList _Rest)
00075   {
00076   First = _First;
00077   Rest = _Rest;
00078   }
00079 
00080 
00081 /** 
00082  * Return a new OpenList constructed from its first and rest.
00083  *
00084  * @param _First the first Object in the list
00085  * @param _Rest list of the rest of the objects in the list
00086  * @return new OpenList from first and rest
00087  */
00088 
00089 public static OpenList cons(Object _First, OpenList _Rest)
00090   {
00091   return new OpenList(_First, _Rest);
00092   }
00093 
00094 
00095 /** 
00096  * Return the first of this non-empty OpenList.
00097  *
00098  * @return first of this list
00099  * @exception OpenListException if this list happens to be empty
00100  */
00101 
00102 public Object first() throws OpenListException
00103   {
00104   if( isEmpty() ) 
00105     {
00106     throw new OpenListException(firstOfOpenListException);
00107     }
00108   return First;
00109   }
00110 
00111 
00112 /** 
00113  * Return the first of the argument, a non-empty OpenList.
00114  *
00115  * @param List the list the rest of which is to be returned
00116  * @return first of the argument list
00117  * @exception OpenListException if the argument happens to be empty
00118  */
00119 
00120 public static Object first(OpenList List) throws OpenListException
00121   {
00122   return List.first();
00123   }
00124 
00125 
00126 /** 
00127  * Return the rest, i.e. all a list of all but the first of this non-empty 
00128  * OpenList.
00129  *
00130  * @return rest of this list
00131  * @exception OpenListException if this list happens to be empty
00132  * will be thrown.
00133  */
00134 
00135 public OpenList rest() throws OpenListException
00136   {
00137   if( isEmpty() ) 
00138     {
00139     throw new OpenListException(restOfOpenListException);
00140     }
00141   return Rest;
00142   }
00143 
00144 
00145 /** 
00146  * Return the rest, i.e. all a list of all but the first of the argument
00147  *  non-empty OpenList.
00148  *
00149  * @parameter List the list the rest of which is to be returned
00150  * @return rest of the argument list
00151  * @exception OpenListException if the argument happens to be empty
00152  */
00153 
00154 public static OpenList rest(OpenList List) throws OpenListException
00155   {
00156   return List.rest();
00157   }
00158 
00159 
00160 /** 
00161  * Return true if this list is empty, false otherwise.
00162  * Note: Done by comparing this list to nil, which should be the <i>only</i>
00163  * way to determine whether the list is empty.
00164  * @return true if this list is empty, false otherwise
00165  */
00166 
00167 public boolean isEmpty()
00168   {
00169   return this == nil;
00170   }
00171 
00172 
00173 /** 
00174  * Return true if this list is non-empty, false otherwise.
00175  * @return true if this list is non-empty, false otherwise
00176  */
00177 
00178 public boolean nonEmpty()
00179   {
00180   return this != nil;
00181   }
00182 
00183 
00184 /** 
00185  * Return true if the argument list is empty, false otherwise.
00186  * Note: Done by comparing this list to nil, which should be the <i>only</i>
00187  * way to determine whether the list is empty.
00188  *
00189  * @param List the OpenList for which emptiness is to be determined
00190  * @return true if the argument list is empty, false otherwise
00191  */
00192 
00193 public static boolean isEmpty(OpenList List)
00194   {
00195   return List.isEmpty();
00196   }
00197 
00198 
00199 /** 
00200  * Return true if the argument list is non-empty, false otherwise.
00201   *
00202  * @param List the OpenList for which non-emptiness is to be determined
00203  * @return true if the argument list is non-empty, false otherwise
00204  */
00205 
00206 public static boolean nonEmpty(OpenList List)
00207   {
00208   return List.nonEmpty();
00209   }
00210 
00211 
00212 /** 
00213  * Create a new list formed by elements of the first argument followed by
00214  * those of the second.
00215  *
00216  * @param L1 the list providing the initial elements of the result
00217  * @param L2 the list providing the final elements of the result
00218  * @return the list containing the elements of the first list followed
00219  * by those of the second
00220  */
00221 
00222 public static OpenList append(OpenList L1, OpenList L2)
00223   {
00224   if( L1.isEmpty() )
00225     {
00226     return L2;
00227     }
00228   else
00229     {
00230     return cons(L1.first(), append(L1.rest(), L2));
00231     }
00232   }
00233 
00234 
00235 /** 
00236  * Return a new list containing the elements of the argument list in
00237  * reverse order.
00238  *
00239  * @param L1 the list providing the elements
00240  * @return the reverse of the argument list.
00241  */
00242 
00243 public static OpenList reverse(OpenList L1)
00244   {
00245   OpenList result = nil;
00246 
00247   for( ; L1.nonEmpty(); L1 = L1.rest() )
00248     {
00249     result = cons(L1.first(), result);
00250     }
00251 
00252   return result;
00253   }
00254 
00255 
00256 
00257 /** 
00258  * Return the number of elements of this list.
00259  * @return the number of elements of this list
00260  */
00261 
00262 public int length()
00263   {
00264   OpenList L  = this;
00265   int result = 0;
00266   for( ; L.nonEmpty(); L = L.rest() )
00267     {
00268     result++;
00269     }
00270 
00271   return result;
00272   }
00273 
00274 
00275 
00276 /** 
00277  * Return the nth element of this list, starting with n = 0, 1, 2, ...
00278  * If there is no nth element, throws an EmptyList exception so indicating.
00279  *
00280  * @param n the index (0, 1, 2, ...) of the desired element.
00281  * @return the nth element of this list.
00282  * @exception OpenListException if there is no nth element
00283  */
00284 
00285 public Object nth(int n) throws OpenListException
00286   {
00287   int remaining = n;
00288   OpenList L  = this;
00289 
00290   try
00291     {
00292     while( remaining > 0 )
00293       {
00294       L = L.rest();
00295       remaining--;
00296       }
00297     return L.first();
00298     }
00299   catch( OpenListException e )
00300     {
00301     throw new OpenListException("nth of an OpenList of length " + length()
00302                               + ", where n == " + n);
00303     }
00304   }
00305 
00306 
00307 
00308 
00309 /** 
00310  * Returns the first n elements of an OpenList.  If there aren't n
00311  * elements in the list, returns the entire list.  If n <= 0, returns nil.
00312  *
00313  * @param n the length of the desired prefix of this list.
00314  * return the prefix of this list of the desired length, or the entire
00315  * list itself if the list is not as long as desired.
00316  */
00317 
00318 public OpenList prefix(int n)
00319   {
00320   if( isEmpty() || n <= 0 )
00321     {
00322     return nil;
00323     }
00324 
00325   return cons(first(), rest().prefix(n-1));
00326   }
00327 
00328 
00329 /** 
00330  * Convert this OpenList to a String, using default punctuation.
00331  *
00332  * @return String representing OpenList
00333  */
00334 
00335 public String toString()
00336   {
00337   return toString(defaultLeftParen, defaultSpacer, defaultRightParen);
00338   }
00339 
00340 
00341 
00342 
00343 /** 
00344  * Convert this OpenList to a String, using the arguments as punctuation.
00345  *
00346  * @param leftParen String that is output before the list elements
00347  * @param spacer String that is output between list elements
00348  * @param rightParen  String that is output after the list elements
00349  * @return String representing OpenList
00350  */
00351 
00352 public String toString(String leftParen, 
00353                        String spacer, 
00354                        String rightParen)
00355   {
00356   StringBuffer buffer = new StringBuffer();
00357 
00358   buffer.append(leftParen);
00359 
00360   if( nonEmpty() )
00361     {
00362     buffer.append(first().toString());
00363     OpenList remainder = rest();
00364 
00365     while( remainder.nonEmpty() )
00366       {
00367       buffer.append(spacer);
00368       buffer.append(remainder.first());
00369       remainder = remainder.rest();
00370       }
00371     }
00372 
00373   buffer.append(rightParen);
00374   return buffer.toString();
00375   }
00376 
00377 
00378 /** 
00379  * test program:
00380  * exercises a variety of the defined methods, printing out results
00381  */
00382 
00383 public static void main(String arg[])
00384   {
00385   try
00386     {
00387     OpenList L0 = nil;
00388 
00389     System.out.println("L0 = " + L0);
00390 
00391     OpenList L1 = cons("a", cons("b", cons("c", nil)));
00392 
00393     System.out.println("L1 = " + L1);
00394 
00395     OpenList L2 = cons(cons("b", cons("c", nil)), cons("d", nil));
00396 
00397     System.out.println("L2 = " + L2);
00398 
00399     OpenList L3 = cons(L1, cons(L2, nil));
00400 
00401     System.out.println("L3 = " + L3);
00402 
00403     OpenList L4 = cons(L1, L2);
00404 
00405     System.out.println("L4 = " + L4);
00406 
00407     OpenList L5 = cons(L2, L1);
00408 
00409     System.out.println("L5 = " + L5);
00410 
00411     OpenList L6 = cons(new Integer(1), nil);
00412 
00413     System.out.println("L6 = " + L6);
00414 
00415     OpenList L7 = cons(new Integer(1),
00416                        cons(new Integer(2),
00417                             cons(new Integer(3),
00418                                  cons(new Integer(4),
00419                                       nil))));
00420 
00421     System.out.println("L7 = " + L7);
00422 
00423     System.out.println("append(L1, L2) = " + append(L1, L2));
00424 
00425     System.out.println("reverse(L5) = " + reverse(L5));
00426 
00427     System.out.println("append(reverse(L7), reverse(L1)) = "
00428                       + append(reverse(L7), reverse(L1)));
00429 
00430     System.out.println("reverse(append(L1, L7)) = "
00431                       + reverse(append(L1, L7)));
00432 
00433     System.out.println("L5.length() = " + L5.length());
00434 
00435     System.out.println("L5.nth(2) = " + L5.nth(2));
00436 
00437     System.out.println("L5.prefix(3) = " + L5.prefix(3));
00438 
00439     System.out.println("L5.nth(4) = " + L5.nth(4));
00440     }
00441   catch( Exception e )
00442     {
00443     System.err.println("*** caught: " + e);
00444     }
00445   }
00446 
00447 }

Generated at Mon Sep 30 00:51:55 2002 for OpenList by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001