Session 15
Programming Recursively — A Review

Please don't rat me out to Kendrick Lamar.
Source: Reddit
Where We Are
For the last few weeks, we have been learning techniques for writing recursive programs based on inductively-defined data. These include one base technique and three ideas to use when the basic technique needs a little help:
- Our basic technique is structural recursion, which asks us to mimic the structure of the data we are processing in our function.
- We use an interface procedure when our structurally-recursive function requires an extra argument in order to do its job.
- We use mutual recursion when our inductive data definition includes two or more data structures defined in terms of one another.
- We sometimes use program derivation to fold the combine the two or more functions produced by mutual recursion into a single function that is more efficient and nearly as easy to read.
We then began using structural recursion to write recursive
functions to answer questions about programs in
a little language
consisting only of variable references, one-argument functions,
and applications (function calls).
(occurs-bound? var exp)
was the first of several functions that process expressions in
the little language.
At the same time, we began using syntax procedures defined for the little language, which allowed us to focus on the meaning of our data rather than their implementation in Racket. Syntax procedures give our little language what we have come to expect from Racket's built-in data types: accessors, type predicates, and constructors.
Today, let's review many of these ideas as you begin to prepare for the quiz. We'll go over problems from Homework 6 and do a few practice problems from previous versions of Quiz 2.
Review of Homework 6
-
Problem 1,
list-index
- "Hint: You will need an interface procedure for this problem." What happens if we don't use one?
-
Problem 2,
tree-sum
-
Trees cannot be empty: A tree is either a number or a list
of size three, containing a number and two trees. This
function does not need a
null?
case, and it does not need to recur on thecdr
of a list. -
Problem 3,
tree?
- This function is a type predicate for trees. It reads exactly like the BNF description of a tree.
-
Problem 4,
unused-var?
-
To solve this problem, you first need to understand that only
lambda
expressions declare variables. With that knowledge, the BNF description guides us toward a solution. Examples like the ones we saw in the opening exercise for Session 14 help us explore the options and trust the code we write.
Two general notes:
-
Some of you are finding ways to solve mutually inductive
problems without following the BNF description. (Some are not.)
But most who do this pay a price: spending too much time and
writing too much code, with duplicated expressions to handle
the
rest
of the list.The idea behind following the pattern is to not reinvent the wheel for every new problem. Software engineers strive to build things in a predictable way and a predictable amount of time. "Going fast" is not a goal, but not going slowly unnecessarily is.
- Using syntax procedures is simply a matter of doing for our own data types what we do for Racket's built-in types. The idea of hiding the implementation of a data type and thinking in terms of its abstractions is not new to this course. One of the most important ideas from your Data Structures course is that we can — and should — do the same for every data type. Think of the push, pop, and top operations for a stack.
Practice Problems
Many students have been asking for more ways to practice writing recursive functions, or to see examples of Quiz 2 problems. Today, let's try to satisfy both kinds of request by working these practice problems drawn from previous Quizzes 2:
(insert n lon)
(nlist++ nlst)
(apply-by-position f lon)
(is-declared? v exp)
These functions all refer to data types you have worked with multiple times before. If you follow the structure of the data closely, each is relatively short. The problems on your quiz will have both of these features, too.
Other Ideas to Review
What other kinds of questions might appear on the quiz? We have studied a number of ideas and techniques that you will want to understand:
-
tail recursion (in
Session 11)
- what is it?
- how does it work?
- what does it mean?
-
free and bound variables (in Sessions
12 and
13)
- how are variables declared?
- what does it mean to say that a variable reference is bound or free?
You will also want to be able to discuss the ideas and techniques linked in Where We Are above, and why we use them.
Wrap Up
-
Reading
- Review the notes for Sessions 8-15.
- Today's notes include two mini-study guides:
-
Homework
- Homework 6 was due yesterday.
-
Quiz 2
- Quiz 2 is next session. We will also get a sneak preview of the next unit of the course, on syntactic abstraction.