Today, we talked about higher-order functions, which also are also called lambdas and commands. Initially, I presented the code for
Append from last lecture again. Then I added other things that you can do to the mix, such as generating a string representation, adding numbers or dividing them. The latter is important, because division is not commutative. I asked the students what is different between these operations and what is the same.
We came to realize that, depending on whether they use forward or backward accumulation, they all follow the same structure. In forward accumulation, they start with an initial value, perform some kind of operation with the initial value and the first of the list, then recur into the rest, using the result of the operation as initial value for the next level of recursion. In backward accumulation, they start with an initial value that is passed all the way to the end of the list. Then, for the empty list, that initial value is returned, and on the way out of the recursion, for each non-empty list, an operation is performed with the first of the list and the return value of the recursion that just finished, and the result is returned to the next level outward.
I then showed this in a more mathematical way, using a binary function f(x, y), and how forward accumulation yields f(f(f(f(i, l1), l2), l3), l4) for forward accumulation and f(l1, f(l2, f(l3, f(l4, i)))) for backward accumulation.
Unfortunately, I had written out our sample list from left to right, beginning with the empty list, as “empty-1-2-3”, instead of “1, 2, 3”, and that caused me to confuse fold left and fold right.
Another small problem occurred during the discussion of lambdas, the way we implement these different operations. The lecture notes provided code for an
Add lambda. In fold left and fold right, the lambdas are binary; however,
Add could process an arbitrary number of parameters. It would even add zero or one numbers. I wanted this to be exactly two — I should have previewed the lecture notes better, beyond the point of checking what code is there, but also precisely what it does. Fortunately, the
Cons lambda was binary.
After we had discussed lambdas and worked out the code for
FoldR, we talked about how to do
Append using fold left and fold right, respectively. We arrived at the interesting result that the operations for both algorithms are the same!
The two things that differ between
Append is that they fold in different directions, and that they use different initial values (empy list and the list to append, respectively).
I thought the material was interesting today, and my motivation and the general arc through the lecture was good, but it was marred by the two mistakes, mostly confusing fold left and fold right.