ListOps.java

/**
 * A non object-oriented way of coding list operations.
 * Each operation is written as a "static" method with one or more lists as
 * parameters. These static methods are the equivalent of Scheme functions.
 * The list parameters are treated as what is called "abstract data types".
 * The instanceof operator is used to check for the type of a given list.
 * @author DXN
 * @since January 2003
*/
public class ListOps {
    /**
     * Computes the length of a list by checking what type of a list it is.
     * Returns 0 if the list an IEmptyList, otherwise recursively computes
     * the length of the rest of the list, adds 1 to the length of the rest,
     * and returns the result.
     * @param L one of the two types of IList.
     * @return an int >= 0
     */
    public static int GetLength(IList L) {
        if (L instanceof IEmptyList) {
            return 0;
        }
        else {
            return 1 + GetLength(((INEList)L).getRest());
            // Note how type-casting is used here!
            // Why do we need to type-cast?
        }

        /*
        The following is an equivalent code, making use of what is called
        the "conditional operator" ?:
        Programmers disagree on whether or not such coding is clear.

        return
            L instanceof IEmptyList ? 0 : 1 + GetLength(((INEList)L).getRest());
        */
    }

    /**
     * Concatenates two lists and returns the result.
     * If the first list is empty then simply returns the second list.
     * Otherwise recursively concatenate the rest of the first list with the
     * the second list, then "cons" the head of the first list to the result.
     * @param L1 the first list.
     * @param L2 the second list to be concatetnated to L1.
     * @return a list consisting of elements in L1 followed by elements in L2.
     */
    public static IList Concatenate(IList L1, IList L2) {
        if (L1 instanceof IEmptyList) {
            return L2;
        }
        else {
            INEList nel = (INEList)L1; // to avoid repeated type-casting
                                       // and messy parentheses.
            return new NEList(nel.getFirst(), Concatenate(nel.getRest(), L2));
        }

        /*
        Using the conditional operator ?:
        Note the "ugly" syntax of type-casting!

        return L1 instanceof IEmptyList ?
                  L2 :
                  NEList(((INEList)L1).getFirst(),
                         Concatenate(((INEList)L1).getRest(), L2));
        */
    }
}