Course
Grades
Email
Welcome
Policies
Grades
Inc
Intgrty
Preface
Part I
Chap 1
Chap 2
Chap 3
XEmacs
Chap 4
Chap 5
Chap 6
Chap 7
Chap 8
Chap 9
Part II
Chap 10
Chap 11
Chap 12
Chap 13
Chap 14
Chap 15
Chap 16
Chap 17
Chap 18
Chap 19
Chap 20
Chap 21
Chap 22
Chap 23
Part III
Chap 24
Chap 25
Chap 26
Chap 27
Chap 28
Chap 29
Chap 30
Chap 31
Chap 32
|
CHAPTER 17: RECURSION ON LISTS, PART 2---SYNTHESIS
- Corrections
-
- page 121, line -13: Change
((+ 3 5) - 6 *
8)) to ((+ 3 5) - 6 *
8)
- page 121, line -7: Change combine-expression to enclose-expression
- Page 297, lines 1 - 11: Change
17.34 (defun enclose-expression (expr)
"EXPR is a list representing an arithmetic
expression (using only the operators + and -)
in normal infix notation.
Returns a list whose one member is EXPR
transformed into Cambridge Prefix Notation."
(check-type expr list)
(cond ((< (length expr) 3) expr)
(t (combine-expr
(second expr) (first expr)
(enclose-expression (nthcdr 2 expr))))))
to
17.34 (defun enclose-expression (expr)
"EXPR is a list representing an arithmetic
expression (using only the operators + and -)
in normal infix notation.
Returns a list whose one member is EXPR transformed
into Cambridge Prefix Notation."
(check-type expr list)
(cond ((< (length expr) 3) expr)
(t (enclose-expression
(combine-expr
(second expr) (first expr) (nthcdr 2 expr))))))
- Notes
-
- Read Chapter 17. This chapter is the heart of the book and the
course. When you have succeeded in doing the exercises through
Chapter 17, you will have earned a grade of C.
- Exercises 17.1 through 17.8 are concerned with the identity of
lists as objects. They use the function
eql as the basic
test of identity. Two Lisp forms form1 and form2 may
evaluate to the identical Lisp object, in which case, (eql
form1 form2) will evaluate to True. If they
don't evaluate to the identically same object, (eql form1
form2) will evaluate to False (that is,
NIL ). It may be that form1 and form2
evaluate to lists that have the same members in the same order, and
yet are not identical, in which case (eql form1
form2) will evaluate to False, even though (equal
form1 form2) will evaluate to True, because
equal is more concerned with appearing the same than
actually being identical. One reason this is important is that lists
can have lists as members. If two members of a list are
eql , that object is stored only once, but if two members
of a list are only equal lists, twice as much storage is
used. Another reason this is important is that many Lisp functions
use eql as the default equality tester, and you might be
surprised at the behavior of these functions if you didn't realize the
difference between eql objects and equal
objects.
These exercises also illustrate the fact that, given a list, some
functions return a list that is eql to the argument list,
or eql to some sublist of it, while other functions copy
all or part of their argument lists. In particular,
append takes two lists, l1 and
l2 , and returns one list that includes a copy of
l1 , but incorporates l2 in it uncopied.
That is, some sublist of (append l1 l2) is
eql to l2 , but no sublist of
(append l1 l2) is eql to
l1 .
What you might do even before doing 17.1 is compare Lisp's value
of
(eql '(a b c) '(a b c))
to its value of
(equal '(a b c) '(a b c))
You'll need a list copying function for Exercise 17.2. Either
create one by doing Exercise 17.1, or just use copy-list
Either use the * technique as specified in these
exercises, or define functions to use. For example, you could do 17.2
by doing
CH17(84): (defun eql-copy (lst)
"Returns T if a list is eql to a copy of itself;
NIL otherwise."
(eql lst (copy-list lst)))
EQL-COPY
CH17(85): (eql-copy '(a b c))
- Notice that there two ways of shadowing a symbol. If you have
already defined a package, and are interacting with the Lisp listener
in that package, and you want to shadow a symbol, just evaluate
(shadow 'symbol) . For example,
USER(82): (defpackage ch17)
#<The CH17 package>
USER(83): ...
USER(99): (shadow 'identity)
But, if you are defining a package and know symbols you want to
shadow, or if you have a defpackage form in a file, you
should use the :shadow subform within the
defpackage form, such as,
USER(82): (defpackage ch17
(:shadow copy-list identity))
#<The CH17 package>
- 17.9: My version of
reverse1 in the book uses
reverse2 as a help function to do all the work. As I say
on page 111, "reverse1 does nothing on its own. It just
initializes reverse2 's second argument to be
() ." An alternative technique is to combine the two
functions into one with an optional argument:
(defun reverse1 (list1 &optional (list2 '()))
"Returns a list consisting of
the members of LIST1 in reverse order
followed by the members of LIST2 in original order.
If LIST2 is omitted, returns a copy of LIST1
with the order of members reversed."
(check-type list1 list)
(check-type list2 list)
(if (null list1) list2
(reverse1 (rest list1)
(cons (first list1) list2))))
Here, if reverse1 is called with two arguments,
list1 is bound to the first argument and
list2 is bound to the second argument. However if
reverse1 is called with only one argument,
list1 is bound to that argument and
list2 is bound to '() .
You should do Exercise 17.9 if you need concrete evidence that
the reverse defined in the book is a lot slower than
reverse1 , in which case you may either use the
reverse1 /reverse2 pair, or the
reverse1 given above with the optional argument.
- Do Exercises 17.9 and 17.10 if you feel they will help your
understanding. Common Lisp already has the function
substitute , which acts like subst* .
- You needn't do Exercises 17.13 - 17.28.
- Do Exercises 17.29 - 17.32, noting the following:
Submit your updated match.cl file. Please remember
to revise the line "This file satisfies the exercises through Exercise
???"
|