CSC 244/444/23 Sep 7/23 Initial Lisp Exercise (Lisp 0) Due: Solutions to questions 3-5 are due Sep 14; feedback will be provided on these questions, but Lisp 0 does not count. Notes: The exercises here are intended to let you see how the most important Lisp functions work; in particular: car, cdr, cons, list, member, find, eq, equal, =, char=, char-equal, member-if, find-if, append, apply, eval, mapcar, cond, if, case, string, coerce, intern, let, setq, backquote, format, defun, loop, dolist, dotimes, return (from loop or prog), return-from, read, Also get acquainted with make-array, aref, make-hash-table, gethash, and defstruct, which will come up in first Lisp assignment (Lisp 1, Sep 16). 1. Find the result of each of the following -- but try to figure out in advance what it will be, and add your own experiments: (car (cons 'this '(that))) (cons 'a (cdr '(a b))) (list '(a b) '(c d) '(e f)) (member 'b '(a b c)) (find 'b '(a b c)) (length '(a (b c) d)) (eq 'a 'a) (eq 'A 'a) (eq '(a b) '(a b)) (equal '(a b) '(a b)) (= 5 5.0) (char= #\a #\a) (char= #\a #\A) (char-equal #\a #\A) (find '(b c) '(a (b c) d)) (find '(b c) '(a (b c) d) :test 'equal) (member-if #'listp '(a (b c) d)) (find-if #'listp '(a (b c) d)) (remove-duplicates '(a b r a c a d a b r a)) (remove-duplicates '((a b) (a b) (a b))) (remove-duplicates '((a b) (a b) (a b)) :test 'equal) (remove 'a '(a b r a c a d a b r a)) (append '(a b) '(c d) '(e f)) (apply #'append '((a b) (c d) (e f))) (apply #'append '(a b) '((c d) (e f))) (apply #'append '(a b) '(c d)); [ERROR] (apply #'append '(a b) '(c d) ((e f))); [ERROR] (eval '(append '(a b) '(c d) '(e f))) (subst 'me 'i '(this is for you and i)) (subst '(you and me) '(any one) '(this is for (any one)) :test 'equal) 355/113 (/ 355/113); first argument of '/' is assumed to be 1 here (/ 355 113) 355./113. ; [ERROR] (/ 355. 113.) (/ 355.0 113) (eval '(/ 355.0 113)) (if (eq 'rose 'rose) 'red 'violet) (let ((x 'rose)) (case x (rose 'red) (violet 'blue) (t 'some_color))) ; only atomic "cases" are allowed; values can be anything (let ((x 'rose)) (cond ((eq x 'rose) 'red) ((eq x 'violet) 'blue) (t 'pink?))) ; conditions and values can be anything; (let ((x '(red rose))) (cond ((eq (car (last x)) 'rose) 'beautiful) (t 'so-so))) (mapcar #'car '((a b) (c d) (e f))) (mapcar #'cdr '((a b) (c d) (e f))) (mapcar #'cadr '((a b) (c d) (e f))) (mapcar #'cons '(a c e) '((b) (d) (f))); NB: TWO arguments after #'cons (mapcar #'(lambda (x) (cons 'a x)) '((b) (d) (f))) (mapcar #'(lambda (x) (cons (case (car x) (b 'a) (d 'c) (f 'e)) x)) '((b) (d) (f))) ((lambda (x) (if (eq x '(a)) 'a 'b)) '(a)) ((lambda (x) (if (equal x '(a)) 'a 'b)) '(a)) ((lambda (x) (if (= x 5) 6 7)) 5.0) ((lambda (x) (if (= x 5) 6 7)) 10/2) (let ((x 'missing)) `(the ,x word)); note use of backquote and comma (string 'this) (format nil "make ~a ~a ~a into a string" 'these 3 'atoms) (format nil "make ~a ~a ~a into a string" '|these| 3 '|atoms|) (format nil "make ~s ~s ~s into a string" "these" 3 '|atoms|) ; using ~s shows escape characters (format t "make ~a ~a ~a into a string" "these" 3 "atoms") ; 't' causes print-out of the successive elements within "..." (format t "make ~s ~s ~s into a string" "these" 3 "atoms"); show escape char's (coerce "these 3 words" 'list) (coerce '(#\t #\h #\i #\s #\.) 'string) (intern "ABC") (setq *name* (read)) 'alice ; good practice: use *...* for global variables, as opposed to ; ones local to a function (e.g., via a 'let' or 'prog') (setq *name* (read)) '(alice blythe) (setq *name* (read-line) Alice Blythe 2. A function for counting atoms: (defun count-atoms (x) ;````````````````````` ; Count the number of atoms occurring anywhere in x ; x: an atom or list structue (cond ((null x) 0) ((atom x) 1) (t (+ (count-atoms (car x)) (count-atoms (cdr x)))) )); end of count-atoms Now write a function definition (defun count-specified-atoms (atm x) ...) that returns the number of occurrences of atm anywhere in x. 3. Write a function that returns all *distinct* atoms occurring in an expression x. First return all atoms, allowing repetition, then apply 'remove-duplicates'. 4. Write a 'root-mean-square' function (defun root-mean-square (xx) ...) that uses 'dolist' to add up the squares of the numbers expected to be on the input list, xx, divides by the number of elements, and then returns the square root of that. It should give an error message if xx is not a list of numbers. Write another version where instead of 'dolist' you use 'loop'; in this case you need to make sure to break out of the loop. You could do this by using a statement of type (setq n (pop input-list)), where 'pop' will return the first element of the input-list, and at the same time replace it by its cdr. Then by checking at each cycle whether input-list is empty, you can do, say, (return nil) to get out of the loop (i.e., the loop will end with nil as its value), and then do the rest of the computation. In a loop (or anywhere in a function definition) if you want to break out of the entire function, returning a value for that function, you would use (return-from ). Actually, 'return-from' is more general, but the above is the usual use. 5. Write a function (defun greet () ...) that says, "Hello, I'm ; who are you?", and then reads what you input as yor name (pick your format, based on the reading examples in exercise (1)), and the says something friendly, including your name. NOTE: ^^^^ @ KEEP LINES TO LESS THAN 80 CHAR LONG -- THE PROGRAMS SHOULD PRINT OUT TIDILY! @ USE INDENTING TO SHOW BLOCK STRUCTURE, EVEN THOUGH IT'S STRICTLY NOT NEEDED!