# CS334: HW 2

#### Table Of Contents

## Reading

**(Required)**Read Mitchell, Chapters 3, 4.1–4.2 (just skim the recursion and fixed point section)**(As Needed)**“Uniprocessor garbage collection techniques”, Paul Wilson.*A thorough overview of collection techniques. (You can most likely skip the details of 3.3–3.6.)*

## Self Check

### Parse Tree

*Mitchell, Problem 4.1*

### Lambda Calculus Reduction

*Mitchell, Problem 4.3*

## Problems

### 1. Reference Counting (15 pts)

*Mitchell, Problem 3.6*

### 2. Parsing and Precedence (10 pts)

*Mitchell, Problem 4.2*

### 3. Symbolic Evaluation (15 pts)

The Lisp program fragment

```
(defun f (x) (+ x 4))
(defun g (y) (- 3 y))
(f (g 1))
```

can be written as the following lambda expression: \[\left(\ \underbrace{(\lambda f.\lambda g. f\ ( g\ 1 ))}_\mathrm{main} \ \underbrace{( \lambda x. x + 4 )}_f\ \right) \ \underbrace{( \lambda y. 3 - y )}_g\]

Reduce the expression to a normal form in two different ways, as described below.

Reduce the expression by choosing, at each step, the reduction that eliminates a \(\lambda\) as far to the

*left*as possible.Reduce the expression by choosing, at each step, the reduction that eliminates a \(\lambda\) as far to the

*right*as possible.In pure \(\lambda\)-calculus, the order of evaluation of subexpressions does not effect the value of an expression. The same is true for Pure Lisp: if a Pure Lisp expression has a value under the ordinary Lisp interpreter, then changing the order of evaluation of subterms cannot produce a different value. However, that is not the case for a language with side effects. To give a concrete example, consider the following “Java”-like code fragment:

`int f(int a, int b) { ... } { int x = 0; System.out.println(f(e1,e2)); }`

Write a function

`f`

and expressions`e1`

and`e2`

for which evaluating arguments left-to-right and right-to-left produces a different result. Your expressions may refer to`x`

. Try it out in your favorite imperative language — C, C++, Java, etc. Which evaluation order is used?

### 4. Lambda Reduction with Sugar (10 pts)

Here is a “sugared” lambda-expression using `let`

declarations:

\[\begin{array}{l} {\tt let}\ \mathit{compose} = \lambda f.\,\lambda g.\, \lambda x.\, f (g\,x)\ {\tt in} \\ \ \ \ \ \ {\tt let}\ h = \lambda x.\,x+x\ {\tt in} \\ \ \ \ \ \ \ \ \ \ \ ((\mathit{compose}\,h)\,h)\,3 \end{array}\]

The “de-sugared” lambda-expression, obtained by replacing each \({\tt let}\ z = U ~{\tt in}~ V\) by \(\\(\lambda z.\,V)\,U\) is

\[\begin{array}{l} (\lambda \mathit{compose}.\, \\ \ \ \ \ \ (\lambda h.\; ((\mathit{compose}\; h)\; h)\; 3) \ \ (\lambda x.\, x+x)) \\ \ \ \ \ \ (\lambda f.\, \lambda g.\, \lambda x.\, f(g\ x)) \end{array}\]

This is written using the same variable names as the `let`

-form in order to make it easier to read the expression.

Simplify the desugared lambda expression using reduction. Write one or two sentences explaining why the simplified expression is the answer you expected.

### 5. Garbage Collection Techniques (20 pts)

Read the Wilson Garbage Collection paper. This paper discusses many foundational ideas behind modern garbage collection. Please answer the following questions with one or two sentences each. **The most credit will be given for clear, concise answers — you should not need to write much.**

What are the limitations of mark-and-sweep and reference-counting collectors?

What problem does copying-collection solve?

What is the main insight behind incremental collection?

What about generational collectors? When will they work well? When will they work poorly?

Most modern collectors use a combination of several techniques to best handle current systems with built-in concurrency and much larger heaps. If you’re curious, have a look at the additional GC papers on the Readings web page, including papers on the HotSpot Java Virtual Machine implements garbarge collection, the Immix collector, and others.

## Programming

### Filter (15 pts)

You may work with a partner on this problem if you’d like. However, it is not required. If you’d like to be matched with a partner, let me know and I’ll pair you up as emails arrive.

Your GitLab account will have a project for your to use for this question. You can follow the same instructions as last week for cloning it and (optionally) adding a partner. You should answer the following in the `hw2.lisp`

file in your repository.

We’ve already seen how using `mapcar`

provides a generic way to easily manipulate collections of data. There are others that are equally useful. We examine one of them in this question.

Write a function

`filter`

that takes a predicate function`p`

and a list`l`

. This function returns a list of those elements in`l`

that satisfy the criteria specified by`p`

. For example, the following two examples filter all negative numbers out of a list and filter all odd numbers out of a list:`* (filter #'(lambda (x) (>= x 0)) '(-1 1 2 -3 4 -5)) (1 2 4) * (defun even (x) (eq (mod x 2) 0)) * (filter #'even '(6 4 3 5 2)) (6 4 2)`

You will need to use the built-in operation

`funcall`

to call the function passed to`filter`

as a parameter. That is, the function`(defun example (f) (funcall f a1 ... an) )`

applies

`f`

to arguments`a1`

–`an`

. You may not use the built-in functions`remove-if`

and`remove-if-not`

in your solution.Suppose that we are using lists to represent sets (in which there are no repeated elements). Use your

`filter`

function to define functions`set-union`

and`set-interset`

that take the union and intersection of two sets, respectively:`* (set-union '(1 2 3) '(2 3 4)) (1 2 3 4) * (set-intersect '(1 2 3) '(2 3 4)) (2 3)`

You may find the built-in function

`(member x l)`

described in the 334 Lisp FAQ handy.Now, use

`filter`

to implement the function`exists`

. Given a predicate function`p`

and a list`l`

, this function returns true if there is at least one`a`

in`l`

such that`(p a)`

returns true:`* (exists #'(lambda (x) (eq x 0)) '(-1 0 1)) t * (exists #'(lambda (x) (eq x 2)) '(-1 0 1)) nil`

You may assume that

`p`

will terminate without crashing for all`a`

.Lastly, the function

`all`

returns true if`(p a)`

is true for all`a`

in`l`

:`* (all #'(lambda (x) (> x -2)) '(-1 0 1)) t * (all #'(lambda (x) (> x 0)) '(-1 0 1)) nil`

Implement this function using

`exists`

. (That is, you should not need to recursively traverse`l`

or use`filter`

directly.)

## What To Turn In

#### Problems

Your submitted homework should:

- be clearly written or typed,
- include your name and HW number at the top,
- list any students with whom you discussed the problems,
- be a single PDF file, with one problem per page, and
- be submitted to Gradescope by the due date.

#### Programming

Your submitted programs should:

- be readonably documented and tested,
- list any students with whom you discussed the programming,
- be committed and pushed to your GitLab repository by the due date, and
- be submitted to Gradescope by the due date.

To submit your code in Gradescope, navigate to the submission page for this assignment’s programming component, and select the option to submit files. Then select and upload your source files. If you worked with a partner, only one of you should submit your code, and please indicate who your partner is when you upload your files.

*Note:* The shared repository you are using is either your own or your partners. The other one will be unused. There is no need to do anything to that repository. Our submission scripts will ignore unused repositories and look only at the onces with completed solutions.