Structure and
Interpretation
of Computer
Programs

Fall 2021
course
site
-->

Mon Sep 27

The assignment for this week is out, and we may spend most of the time in class just letting you work on that.

But I though it would be useful to give you a bit of a preview and motivation for some of the functional programming that we're heading into now.

Remember that chap 1 in the text is "function only", which at times means some gymnastics to use only concrete "things" rather than lists, while chap 2 is "data structures with cons".

fold

Some of this is adapted from en.wikipedia.org/wiki/Fold_(higher-order_function) .

We start with

a binary operation     -
a starting value       0
a sequence             (1 2 3)

and want a function that will combine two terms to give a result, then combine that result with the next, and so on.

There are two ways to organize this, starting either on the right or the left, which are (strangely enough) called fold-left and fold-right. Following a common convention, I'll name them foldl and foldr.

In both cases, we're treating the list as singly-linked from the left, the same cons list that we've already seen in scheme, and so the structure of the computation is different for the two cases.

For a non-associative operator like - where (1-2)-3 != 1-(2-3), foldl and foldr give different results.

For associative operations like +, the final answer is the same either way, so for example (1+2)+3 == 1+(2+3) .

Let's consider how to compute this, expressed using regular infix "a+b" math notation to start.

1 - 2 - 3 - 4

fold right

If we start on the right, and use the z (zero) when we start, then the grouping is

(1 - (2 - (3 - (4 - 0)))

which using the scheme convention of operators on the left is

(- 1 (- 2 (- 3 (- 4 0))))

And we'll call that foldr.

(foldr op initial sequence) i.e. (foldr - 0 '(1 2 3 4))

It turns out that foldr has the advantage that it can be handled in a "lazy" way, in that it has a simple recursive definition that let's us look at the first item in the sequence, and then apply the definition to the rest, perhaps without completing the rightwards part all the way out.

Thus the notion of "what happens first" isn't quite as straightfoward as one might think. It depends on what you mean by "happens". The functional programming folks take advantage of "lazy" by allowing for example sequences of infinite length ... as long as you only do what you need to, without performing the whole calculation. As far as the definition goes, the foldr definition of "what happens to the first term" doesn't need the rest of the sequence ... as long as you don't mind recursion. ;)

fold left

If on the other hand we start on the left, then we have

((((0 - 1) - 2) - 3) - 4)

or using our scheme notation

(- (- (- (- 0 1) 2) 3) 4)

And we'll call that foldl.

(foldl op initial sequence) i.e. (foldl - 0 '(1 2 3 4))

It turns out that this version has the advantage that we can write it efficiently in a tail recursive form, using a storage result to keep track of what we've done so far, in the same way that a "for-loop" works in a typical intro programming course.

However, as is apparent from the (- (- (- (- ...) start of foldl in our scheme notation, in terms of function calls since the first call is the innermost one, the leftmost function call is actually the last one, and so this cannot be run partially on an infinite or indefinite length list - it would just go into an infinite loop.


These ideas generalize in some interesting ways when working with trees and lists.

Fold (also called "reduce") is one of the several classic looping constructs, related to programming ideas like

map                  en.wikipedia.org/wiki/Map_(higher-order_function)
each                 en.wikipedia.org/wiki/Foreach_loop
filter               en.wikipedia.org/wiki/Filter_(higher-order_function)
pipeline             en.wikipedia.org/wiki/Pipeline_(software)
higher order func    en.wikipedia.org/wiki/Higher-order_function
apply                en.wikipedia.org/wiki/Apply

coding

Let's see if we can code these two functions together in class, in scheme, put in some debugging statements to see what happens in what order, and do some tests on some short lists.

4:45pm : I've attached the code files that we did today:

https://cs.bennington.college /courses /fall2021 /sicp /notes /09-27
last modified Mon September 27 2021 4:49 pm

attachments [paper clip]

  last modified size
TXT dot.scm Mon Sep 27 2021 04:47 pm 391B
TXT fold.scm Mon Sep 27 2021 04:47 pm 1.2K