/* An interface to a list of strings.  We will implement
   this interface so that we never _change_ existing
   StringLists, only create new ones (this can be useful
   practically, and will help us out pedagogically). */

interface StringList {
  /* Returns the number of strings in the list */
  int length();

  /* Returns a new StringList that contains the String s
     first, followed by the existing elements */
  StringList add(String s);

  /* Returns true if the string is contained in the list,
     false otherwise */
  boolean contains(String s);

  /* Returns the item at the given index, or null
     if not found */
  String get(int index);
}

class SLLink implements StringList {
  String value;
  StringList rest;
  public SLLink(String value, StringList rest) {
    this.value = value;
    this.rest = rest;
  }
  public int length() {
    return 1 + this.rest.length();
  }
  public StringList add(String s) {
    return null;
  }
  public boolean contains(String s) {
    return false;
  }
  public String get(int index) {
    return null;
  }
  public String toString() {
    return "SLLink(\"" + this.value + "\", " + this.rest.toString() + ")";
  }
}

class SLEmpty implements StringList {
  public int length() {
    return 0;
  }
  public StringList add(String s) {
    return null;
  }
  public boolean contains(String s) {
    return false;
  }
  public String get(int index) {
    return null;
  }
  public String toString() {
    return "SLEmpty";
  }
}

public class Links {
  public static void main(String args[]) {
    StringList s1 = new SLLink("a", new SLLink("b", new SLEmpty())); 
    System.out.println(s1);
    System.out.println(s1.length());
    //System.out.println(s1.toString());

    /*
    A: "a", "b", "SLEmpty"
    B: "a", "b"
    C: SLLink("a", "b", SLEmpty)
    D: SLLink("a", SLLink("b", SLEmpty))
    */
  }
}


/*

A:
// In SLLink
public boolean contains(String s) {
  return (this.value == s) || this.rest.contains(s);
}
// In SLEmpty
public boolean contains(String s) {
  return false;
}

B:
// In SLLink
public boolean contains(String s) {
  return (this.value == s);
}
// In SLEmpty
public boolean contains(String s) {
  return false;
}

C:
// In SLLink
public boolean contains(String s) {
  return (this.value == s) || this.rest.contains(this.value);
}
// In SLEmpty
public boolean contains(String s) {
  return false;
}

*/
