[Texas PLT logo]

COMP 202: Principles of Object-Oriented Programming II

  Higher Order Functions  

Today's Menu:

Abstraction of Data Movement

In many situations, processing a list involves processing the first element of a list (in the case of a non-empty list) and moving the result along the list structure in a sequential manner.  The previous two examples (reversing a list and concatenating two lists) illustrate two common data movements:

These two common ways of list processing can be abstracted into

Abstract function of a variable number of parameters

Examples

1. Adding an open-ended number of Integer ogbjects.

2. "Consing" a list to form a new list.

 

 

Forward Accumulation Visitor: Foldl "fold left"

Uses an ILambda to process a list from front to end.

Functional definition:

IList (Immutable List) LRStruct (Mutable list)
public class FoldL implements IListAlgo {

    private ILambda _f;

    public FoldL(ILambda f) {
        _f = f;
    }


public class FoldlLRS implements IAlgo {

    private ILambda _f;

    public FoldlLRS(ILambda f) {
        _f = f;
    }

// empty case: in class exercise
public Object emptyCase(IMTList h, Object... b) {
    return b[0];
}
// empty case: in class exercise
public Object emptyCase(LRStruct h, Object
... b) {
   // class exercise
}
// non-empty case: in class exercise
public Object nonEmptyCase(INEList h, Object... b) {
  return h.getRest().execute(this, _f.apply(h.getFirst(), b));
}

}

// non-empty case: in class exercise
public Object nonEmptyCase(LRStruct h, Object
... b) {
   // class exercise
}

}

Reverse Accumulation Visitor: Foldr "fold right"

Uses an ILambda to process a list from end to front.

Functional definition:

IList (Immutable List) LRStruct (Mutable list)
public class FoldR implements IListAlgo {

    private ILambda _f;

    public FoldR(ILambda f) {
        _f = f;
    }


public class FoldrLRS implements IAlgo {

    private ILambda _f;

    public FoldrLRS(ILambda f) {
        _f = f;
    }

// empty case: in class exercise
public Object emptyCase(IMTList h, Object... b) {
   // class exercise
}
// empty case: in class exercise
public Object emptyCase(LRStruct h, Object... b) {
   // class exercise
}
// non-empty case: in class exercise
public Object nonEmptyCase(INEList h, Object... b) {
   // class exercise
}

}

// non-empty case: in class exercise
public Object nonEmptyCase(LRStruct h, Object... b) {
   // class exercise
}

}

Food for thoughts: Rewrite Reverse and Append using Foldl and/or Foldr

Study the following JUnit test code to see how reversing a list is done using FoldL.

 

As one can see from the above, to reverse a list, all we have to do is fold left using "cons" as the processing function.

We leave it as an exercise to concatenate two lists using an appropriate fold operation together with an appropriate ILambda.

 

Download the source code for this lecture and lecture 2. Note that Reverse and Append have also been implemented using FoldL and FoldR. In the unit tests, you can see that both reversing and appending use the same operation!

The only difference is which way we fold (left to reverse, right to append), and what we use as initial value (empty list to reverse, the 2nd list to append). Now that's code reuse!

 

  Higher Order Functions  

URL: http://www.cs.rice.edu/teaching/202/08-fall/lectures/higherOrder/index.shtml
Copyright © 2008-2010 Mathias Ricken and Stephen Wong