solution-ch02

advertisement
ANSI Common Lisp: 2 Welcome to Lisp
June 10, 2003
2.1 Describe what happens when the following expressions are evaluated.
Solution:
cl-user(98): (+ (- 5 1) (+ 3 7))
14
cl-user(99): (list 1 (+ 2 3))
(1 5)
cl-user(100): (if (listp 1) (+ 1 2) (+ 3 4))
7
cl-user(101): (list (and (listp 3) t) (+ 1 2))
(NIL 3)
2.2 Give three distinct cons expressions that return (a b c).
Solution:
cl-user(106): (cons 'a (cons 'b (cons c nil)))
(A B C)
cl-user(107): (cons 'a '(b c))
(A B C)
cl-user(112): (cons 'a (cons 'b '(c)))
(A B C)
2.3Using car and cdr, define a function to return the fourth element of a list.
Solution:
(defun my-fourth (x)
(car (cdr (cdr (cdr x)))))
2.4 Define a function that takes two arguments and returns the greater of the two.
Solution:
(defun greater (x y)
(if (and (numberp x) (numberp y))
(if (> x y) x y)))
2.5 What do these function do?
Solution:
(a)
(defun enigma (x)
(and (not (null x))
(or (null (car x))
(enigma (cdr x)))))
Returns NIL in any situation.
(b)
(defun mystery (x y)
(if (null y)
nil
(if (eql (car y) x)
0
(let ((z (mystery x (cdr y))))
(and z (+ z 1))))))
If (member x y), returns x's index in y (starting from 0). Otherwise, returns NIL.
2.6 What could occur in place of the x in each of the following exchanges?
Solution:
(a) (car (x (cdr '(a (b c) d))))
B
(car (car (cdr '(a (b c) d))))
(b) (x 13 (/ 1 0))
13
(if t 13 (/ 1 0))
(c) (x #'list 1 nil)))
(1)
(list (car (funcall #'list 1 nil)))
2.7 Using only operators introduced in this chapter, define a function that takes a list as an
argument and returns true if one of its elements is a list.
Solution:
(defun element-listp (x)
(if (null x)
nil
(if (listp (car x))
t
(element-listp (cdr x)))))
cl-user(23): (element-listp (list 1 2 3))
NIL
cl-user(24): (element-listp ())
NIL
cl-user(25): (element-listp (list 1 2 (list 3 4) 5 6))
T
2.8 Give iterative and recursive definitions of a function that
(a) takes a positive integer and prints that many dots.
(b) takes a list and returns the number of times the symbol a occurs in it.
Solution:
(a)
(defun print-dots (n)
(if (or (not (numberp n))
(<= n 0))
(format t "The argument should be a positive integer.~%")
(do ((i 1 (+ i 1)))
((> i n))
(format t "."))))
(defun print-dots-recursive (n)
(if (or (not (numberp n))
(< n 0))
(format t "The argument should be a positive integer.~%")
(cond ((not (= n 0))
(format t ".")
(print-dots-recursive (- n 1))))))
(b)
(defconstant sym 'a)
(defun symbol-count-iter (x)
(let ((count 0))
(if (not (listp x))
(format t "The argument should be a list.")
(dolist (obj x)
(if (eql sym obj)
(setq count (+ count 1)))))
count))
(defconstant sym 'a)
(defun symbol-count-recursive (x)
(if (not (listp x))
(format t "The argument should be a list.")
(if (null x)
0
(if (eql sym (car x))
(+ 1 (symbol-count-recursive (cdr x)))
(symbol-count-recursive (cdr x))))))
2.9 A friend is trying to write a function that returns the sum of all the non-nil elements in a list.
He has written two versions of this function, and neither of them work. Explain what’s wrong
with each and give a correct version.
Solution:
(a)
(defun summit (lst)
(remove nil lst)
(apply #'+ lst))
The remove function is non-destructive, that is, it will return the modified list, but won't modify
the input list itself. The correct version is:
(defun summit (lst)
(apply #'+ (remove nil lst)))
(b)
(defun summit (lst)
(let ((x (car lst)))
(if (null x)
(summit (cdr lst))
(+ x (summit (cdr lst))))))
This recursive version has no termination point. So, it will runs for ever even the (cdr x) is
empty, until the stack is overflowed. The correct version is:
(defun summit (lst)
(let ((x (car lst)))
(if (null lst)
0
(if (null x)
(summit (cdr lst))
(+ x (summit (cdr lst)))))))
Download