This homework has three types of problems:
Self Check: You are strongly encouraged to think about and work through these questions, but you will not submit answers to them.
Problems: You will turn in answers to these questions.
Programming: This part involves writing Lisp code. You may work with a partner on it if you like.
(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.)
Mitchell, Problem 4.1
Mitchell, Problem 4.3
Mitchell, Problem 3.6
Mitchell, Problem 4.2
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:
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?
Here is a "sugared" lambda-expression using let
declarations:
The "de-sugared" lambda-expression, obtained by replacing each {\tt let}\ z = U ~{\tt in}~ V by \\(\lambda z.\,V)\,U is
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.
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.
a. What are the limitations of mark-and-sweep and reference-counting collectors?
b. What problem does copying-collection solve?
c. What is the main insight behind incremental collection?
d. 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.
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
You should not need to recursively traverse directly.
Submit your homework via GradeScope by the beginning of class on the due date.
Submit your answers to the Gradescope assignment named, for example, "HW 1". It should:
You will be asked to resubmit homework not satisfying these requirements. Please select the pages for each question when you submit.
If this homework includes programming problems, submit your code to the Gradescope assignment named, for example, "HW 1 Programming". Also:
Autograding: For most programming questions, Gradescope will run an autograder on your code that performs some simple tests. Be sure to look at the autograder output to verify your code works as expected. We will run more extensive tests on your code after the deadline. If you encounter difficulties or unexpected results from the autograder, please let us know.