// file:    StringList.java
// author:  Robert Keller
// purpose: expansion of the StringList class, open list of Strings

// In the open list concept, a list is identified with a reference to the 
// first cell of the list.  
//
// The empty list is called nil, which happens to be identified with
// the null reference null.  However, use of nil is preferred because
// other list models to come later will not use this implementation of nil.
//
// cons(F, R)  creates an StringList from a String F and a StringList R.
// first(L)    returns the first of a non-empty list.
// rest(L)     returns all but the first of a non-empty list.
// isEmpty(L)  tells whether L is empty.
// print(L, S) prints StringList L in PrintStream S

import java.io.PrintStream;

// The StringList class actually defines a cell containing the first and rest.
// It thus contains the entire list only in a figurative sense.

class StringList
{
static final StringList nil = null;	     // the empty StringList

String First;                                // every non-empty list has
StringList Rest;                             // these two things


static StringList cons(String First, StringList Rest) // create a new StringList
  {
  return new StringList(First, Rest);        // see constructor below
  }


static String first(StringList L)            // get First
  {
  return L.First;
  }


static StringList rest(StringList L)         // get Rest
  {
  return L.Rest;
  }


static boolean isEmpty(StringList L)         // tell whether empty
  {
  return L == nil;
  }


// StringList constructor

StringList(String First, StringList Rest) 
  {
  this.First = First;
  this.Rest = Rest;
  }


// println prints StringList as (alpha beta gamma ....) followed by new line

static void println(PrintStream S, StringList L)
  {
  print(S, L);
  S.println();
  }


// print prints IntList as (alpha beta gamma ....)

static void print(PrintStream S, StringList L)  
  {
  S.print("(");                 // print opening "("
  
  if( !isEmpty(L) )
    {
    S.print(first(L));          // print first element if any

    L = rest(L);
  
    while( !isEmpty(L) )        // print rest of elements
      {
      S.print(" ");
      S.print(first(L));
      L = rest(L);
      }
    }

  S.print(")");                 // print closing ")"
  }


// test program

public static void main(String arg[])
  {
  StringList L = cons("alpha", cons("beta", cons("gamma", cons("delta", nil))));

  System.out.print("L = "); 
  println(System.out, L); 

  System.out.println("first(L) = " + first(L)); 

  System.out.print("rest(L) = "); 
  println(System.out, rest(L)); 

  System.out.println("first(rest(L)) = " + first(rest(L))); 

  System.out.print("rest(rest(L)) = "); 
  println(System.out, rest(rest(L))); 

  System.out.print("nil = "); 
  println(System.out, nil); 
  }
}

