Session 15
Programming Recursively — A Review

A 2x2 grid using the meme Drakeposting meme.  The upper left is Drake looking away, shielded by his hand. In the upper right is the phrase 'NO INFINITE RECURSION'. In the lower left, Drake smiles and points ahead. The lower right panel is an image of the full 2x2 comic, recursive in the lower right panel.
Yes, Dr. Wallingford is drakeposting a recursion meme.
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:

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, tree-min
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 the cdr or the rest of the list.
Problem 3, tree-contains?
This function is a member-like predicate for trees. The structure is nearly identical to tree-min.
Problem 1, count-operators
You don't need an interface procedure for this problem. Writing loops has trained us to create a "sum" variable and then add to it on each pass through the loop. But when we receive a tree with an operator and two sub-trees, we can find the number of operators in each sub-tree and then add up three numbers.
Problem 4, count-lambdas
This is quite similar to count-operators, with two recursive cases. Each lambda expression creates one lambda, plus however many are created in the lambda's body. Applications do not create lambdas directly, but each part of an application might. Count them and add the totals.
Problem 5, declared-vars
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. This is similar to counting lambdas, but:
  1. We access the formal parameter of each function.
  2. Instead of counting 1 for each parameter, we put it in a list of symbols.
This include the base case: declared-vars returns a list... in all cases!

Two general notes:

Practice Problems

Some 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:

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.

Note: We ran a little short of time to solve (contains-varref? v exp) completely in class.
Try to solve it on your own before looking at the solution in the code file.

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:

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