The Department of Computer Science & Engineering
 STUART C. SHAPIRO: CSE 202

# CSE202:Programming in Lisp

 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) # 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)) # ``` 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: 17.29 & 17.30: Review the discussion of association lists in the Notes for Exercise 16.14 and for the function `monthNumber`. You are permitted to use `assoc` in the definitions you are writing, so your definitions of `boundp` and `bound-to` can be extremely short. 17.31: If pat and lst are of different lengths, `match` should return `NIL`. The third argument of `match1`, called `pairs` in the text is a substitution (an association list). Review the discussion of `reverse1` above. Rather than defining `match` and `match1` as suggested in the book, you may prefer to define `match` to be a function that takes an optional argument that should default to `((T T))`, for example ```(defun match (pat lst &optional (pairs '((T T)))) ... ) ``` 17.32: You could write your ```(substitute pat subs)``` either by recursing down `pat` or by recursing down `subs`. Since patterns tend to be a lot longer than substitutions, the former is a better idea, and that way, you get to use your `boundp` and `bound-to` functions. Submit your updated `match.cl` file. Please remember to revise the line "This file satisfies the exercises through Exercise ???"