/* RecursiveListUtilsInt.java ** An instance of this class has several methods providing utilities for ** recursive lists containing Integer objects. ** It specializes RecursiveListUtils.java by replacing all generic type ** parameters by Integer. Also removes all code pertaining to counting ** the number of method calls. */ public class RecursiveListUtilsInt { /* Returns the length of (i.e., # of elements in) the given list. */ public int lengthOf(RecursiveList list) { if (list.isEmpty()) { return 0; } else { return 1 + lengthOf(list.tailOf()); } } /* Returns a recursive list whose elements are those in the given ** array, and in the same order. ** Void: The second parameter is for the purpose of providing a ** "factory" (i.e., a means of creating a new (empty) list). */ public RecursiveList listify(int[] a) // RecursiveList factory) { RecursiveList result = RecursiveListEmpty.emptyListFactory(); //System.out.println("Upon creating empty list, have: " + result); // Place array elements into the list from the end of the array // to the beginning. for (int i = a.length; i != 0; i--) { result = result.cons(a[i-1]); //System.out.println("After inserting " + a[i-1] + " have " + result); } return result; } /* Returns a new array containing the items in the given list, in the same order. */ public int[] arrayify(RecursiveList list) { int[] result = new int[lengthOf(list)]; for (int i=0; i != result.length; i++) { result[i] = list.headOf(); list = list.tailOf(); } return result; } /* Returns true iff some element in the given list is equal to the ** given item. ** Void: (according to item's equals() method). */ public boolean occursIn(int item, RecursiveList list) { if (list.isEmpty()) { return false; } else { return item == list.headOf() || occursIn(item, list.tailOf()); } } /* Returns the list that results from appending the second given list ** to the end of the first one. */ public RecursiveList append(RecursiveList first, RecursiveList second) { if (first.isEmpty()) { return second; } else { // Recursively append the second list onto the end of the first // one's tail and then insert the first one's head! RecursiveList allButHead = append(first.tailOf(), second); return allButHead.cons(first.headOf()); } } /* Returns a list containing the same elements as the given one, but ** in reverse order. */ public RecursiveList reverse(RecursiveList list) { if (list.isEmpty()) { return list; } else { RecursiveList justHead = list.emptyList().cons(list.headOf()); return append(reverse(list.tailOf()), justHead); } } /* This is a more efficient version of the method above. */ public RecursiveList reverse2(RecursiveList list) { return reverse2Aux(list, list.emptyList()); } /* Auxiliary to the method above, this one returns the list obtained ** by appending the reverse of 'yetToBeRev' onto the end of 'alreadyRev'. ** The parameter names are meant to suggest that this method "expects" ** to receive, in 'yetToBeRev', an intact suffix of the list whose ** reverse is to be constructed and, in 'alreadyRev', the ** already-reversed complementary prefix of that list. ** ** The technique employed here is that of the "accumulating parameter", ** in which one of the method's parameters serves as a partial result ** and is augmented as the recursive calls go deeper and deeper. When ** the base case is reached, the accumulating parameter is the desired ** result (or at least the desired result can be obtained from it ** relatively easily). Here, the accumulating parameter is 'alreadyRev'. */ private RecursiveList reverse2Aux(RecursiveList yetToBeRev, RecursiveList alreadyRev) { if (yetToBeRev.isEmpty()) { return alreadyRev; } else { return reverse2Aux(yetToBeRev.tailOf(), alreadyRev.cons(yetToBeRev.headOf())); } } }