package playingWithLists;

public class MySchemeListTest {
	
	public static void main(String[] args) {
		
		// construct nil (empty list)
		MySchemeList<Integer> anEmptyList = new MySchemeList<Integer>();
		System.out.println("anEmptyList: "+anEmptyList);
		
		// construct a list with car 4 and nil 
		MySchemeList<Integer> aListWithFour = anEmptyList.cons(4);
		System.out.println("aListWithFour: "+aListWithFour);
		
		// construct a list with car 3 and cdr aListWithFour
		MySchemeList<Integer> aListWithThreeAndFour = aListWithFour.cons(3);
		System.out.println("aListWithThreeAndFour: "+aListWithThreeAndFour);
		
		// you get the picture: construction of lists using 
		// cons looks "backward" when object-oriented notation is used:
		
		MySchemeList<Integer> aList = 
			anEmptyList.cons(4).cons(3).cons(2).cons(1);
			
		/* TEST 1: print out list */
		
		System.out.println("TEST 1: printing list [1,2,3,4]");
		System.out.println(aList);
		
		/* TEST 2: cons */
		
		System.out.println("TEST 2: cons [1,2,3,4] with 0");
		System.out.println(aList.cons(0));
			
		/* TEST 3: car and cdr */
		
		System.out.println("TEST 3: car and cdr, 3 x cdr and 1 x car called in [1,2,3,4]");
		System.out.println(aList.cdr().cdr().cdr().car());
		// note that "going down" a list looks somewhat nicer in 
		// object-oriented syntax, than in Scheme
		// (car (cdr (cdr (cdr alist))))
			
		/* TEST 4: setCar */
		
		System.out.println("TEST 4: setCar of [1,2,3,4] to 5");
		aList.setCar(5);
		System.out.println(aList);
			
		/* TEST 5: setCdr */
		
		System.out.println("TEST 5: setCdr, change last element of [5,2,3,4] to [10,20]");
		aList.cdr().cdr().setCdr(new MySchemeList<Integer>().cons(20).cons(10));
		System.out.println(aList);
		
		/* TEST 6: circular list */
		
		System.out.println("TEST 6: circular list, set cdr third element in [5,2,3,10,20] to the start of the list");
		aList.cdr().cdr().setCdr(aList);
		System.out.println(aList);
		// observe how the method toString() in MySchemeList limits the
		// printing depth
	}

}
