## Session 9 Extension

### Recap: The remove-first Function

We just wrote a function named remove-first that takes two arguments, a symbol s and a list of symbols los. It returns a list just like los minus only the first occurrence of s.

```    (define remove-first
(lambda (s los)
(if (null? los)
'()
(if (eq? (first los) s)
(rest los)
(cons (first los)
(remove-first s (rest los)))))))
```

It works:

```    > (remove-first 'a '(a b c))
'(b c)

> (remove-first 'b '(a b c))
'(a c)

> (remove-first 'd '(a b c))
'(a b c)

> (remove-first 'a '())
'()

> (remove-first 'a '(a a a a a a a a a a))     ; count 'em up!
'(a a a a a a a a a)
```

A quick exercise: before moving forward: Suppose that, instead of

```                (cons (first los)
(remove-first s (rest los)))
```
as the 'else' clause of the second if, we had just
```                (remove-first s (rest los))
```
What function would remove-first then compute?

### The remove Function

What if we wanted to remove all occurrences of a symbol from a list of symbols?

The function remove behaves like remove-first, but it removes all occurrences of the symbol, not just the first. The structure of remove-first and remove are so similar that we can focus on how to modify remove-first to convert it into remove.

In terms of our code, how does the new function differ from remove-first?

• In the base case, our answer is still the empty list.

• If the first item in the list does not match the item to remove, then we still need to cons it onto the solution to the recursive step.

• If the first item in the list does match the item to remove, then we need to do something different!

So:

```    (define remove
(lambda (s los)
(if (null? los)                         ; on an empty list, the
'()                                 ; answer is still empty
(if (eq? (first los) s)

;; WHAT DO WE DO HERE?

(cons (first los)               ; we still have to preserve
(remove s (rest los)))    ; non-s symbols in los
))))
```

In remove-first, as soon as we find s we return the rest of the los, into which are consed any non-s symbols that preceded s in los. But in remove, we need to be sure to remove not just the first s (by returning the rest of los) but all the s's, including any that may be lurking in (rest los). So:

```    (define remove
(lambda (s los)
(if (null? los)
'()
(if (eq? (first los) s)
(remove s (rest los))       ;; *** HERE IS THE CHANGE! ***
(cons (first los)
(remove s (rest los)))))))

> (remove 'a '(a b c))
(b c)

> (remove 'a '(a a a a a a a a a a))
()
```

Notice the relationship between the structure of the data and the the structure of our code. The structure of the data did not change from remove-first to remove, so neither did the structure of the function. A small change in spec resulted in a small change in code.

remove-first and remove demonstrate the basic technique for writing recursive programs based on inductive data specifications. This is a pattern you will find in many programs, both functional and object-oriented. We call this pattern structural recursion.

Eugene Wallingford ..... wallingf@cs.uni.edu ..... February 14, 2023