Now that we have taken the step to making every list an object, even the empty list, we may as well introduce non-static methods for accessing the components of a list.
In this scheme, rather than having to say, outside the class,
StringList.first(L)
with an appropriate set of definitions, we could just say
L.first()
Here the type (class) of variable L is what determines which method to use; we don't have to state the class name in the method, which makes the code more readable.
Here are the definitions, which could be in addition to those we have already given. That is, the methods first, rest, etc. would be overloaded as both static and regular methods.We show both methods together below, but could get rid of the static ones.
class StringList{StringCell handle;
static String first(StringList L){return handle.first;}
String first(){return handle.first;}
static StringList rest(StringList L){return handle.rest;}
StringList rest(){return handle.rest;}
static boolean isEmpty(StringList L){return handle == null;}
boolean isEmpty(){return handle == null;}
static StringList cons(String first, StringList rest){return new StringList(new StringCell(first, rest));}
StringList cons(String first){return new StringList(new StringCell(first, this));}
StringList(StringCell handle){this.handle = handle;}
final static nil = new StringList(null); // note that nil != null}
class StringCell{String first;StringList rest;
StringCell(String first, StringList rest){this.first = first;this.rest = rest;}}
Here is some code using the new style; see how you like it:
public String toString(){StringBuffer b = new StringBuffer();b.append("(");StringList L = this;if( !L.isEmpty() ){b.append(L.first());L = L.rest();while( !L.isEmpty() ){b.append(" ");b.append(L.first());L = L.rest();}}b.append(")");return b.toString();}
Next Slide | Previous Slide | Contents |