DATA ABSTRACTION AND MAPPING ------------------------------------------------------------------------------------------ Data Details Stifle Progress (setf book-example-1 '((Artificial Intelligence) ;Title. (Patrick Henry Winston) ;Author. (Technical AI))) ;Classification. * (second book-example-1) (Patrick Henry Winston) (first (rest <book description>)) ;One method. (second <book description>) ;Another method. (first (nthcdr 1 <book description>)) ;Still another method. (setf book-example-2 '((title (Artificial Intelligence)) (author (Patrick Henry Winston)) (classification (Technical AI)))) * (assoc 'author book-example-2) (AUTHOR (PATRICK HENRY WINSTON)) * (second (assoc 'author book-example-2)) (PATRICK HENRY WINSTON) (setf book-example-3 '(((title (Artificial Intelligence)) (author (Patrick Henry Winston)) (classification (Technical AI))) ((loaned-to (Karen Prendergast)) (loaned-on (26 May 88))))) ------------------------------------------------------ Data Abstraction Facilitates Progress (defun book-author (book) ;Data is in a simple list. (second book)) (setf book-example-1 '((Artificial Intelligence) ;Title. (Patrick Henry Winston) ;Author. (Technical AI))) ;Index terms. * (book-author book-example-1) (PATRICK HENRY WINSTON) (defun book-author (book) (second (assoc 'author book))) (setf book-example-2 '((title (Artificial Intelligence)) (author (Patrick Henry Winston)) (classification (Technical AI)))) * (book-author book-example-2) (PATRICK HENRY WINSTON) (defun book-author (book) ;Data is in a list of association lists. (second (assoc 'author (first book)))) (setf book-example-3 '(((title (Artificial Intelligence)) (author (Patrick Henry Winston)) (classification (Technical AI))) ((loaned-to (Karen Prendergast)) (loaned-on (26 May 88))))) * (book-author book-example-3) (PATRICK HENRY WINSTON) --------------------------------------------------- You Should Use Readers, Constructors, and Writers Liberally (defun make-book (title author classification) (list (list 'title title) (list 'author author) (list 'classification classification))) * (setf book-example-4 (make-book '(common Lisp) '(Guy Steele) '(Technical Lisp))) ((TITLE (COMMON LISP)) (AUTHOR (GUY STEELE)) (CLASSIFICATION (TECHNICAL LISP))) (defun book-title (book) (second (assoc 'title book))) (defun book-author (book) (second (assoc 'author book))) (defun book-classification (book) (second (assoc 'classification book))) (defun book-author-writer (book author) (cons (list 'author author) book)) * (setf book-example-4 (book-author-writer book-example-4 '(Guy L Steele))) ((AUTHROR (GUY L STEELE)) (TITLE (COMMON LISP)) (AUTHOR (GUY STEELE)) (CLASSIFICATION (TECHNICAL LISP))) * (book-author book-example-4) (GUY L STEELE) (defun book-author-writer (book author) (if (eql 'author (first (first book))) (cons (list 'author author) (rest book)) (cons (first book) (book-author-writer (rest book) author)))) * (setf book-example-4 (book-author-writer book-example-4 '(Guy L Steele))) ((TITLE (COMMON LISP)) (AUTHOR (GUY L STEELE)) (CLASSIFICATION (TECHNICAL LISP))) * (book-author book-example-4) (GUY L STEELE) --------------------------------------------------------- It Is Useful To Transform and To Filter (setf books (list (make-book '(artificial intelligence) '(patrick henry winston) '(technical ai)) (make-book '(common lisp) '(guy l steele) '(technical lisp)) (make-book '(moby dick) '(herman melville) '(fiction)) (make-book '(tom sawyer) '(mark twain) '(fiction)) (make-book '(the black orchid) '(rex stout) '(fiction mystery)))) ((PATRICK HENRY WINSTON) (GUY L STEELE) (HENRY MELVILLE) (MARK TWAIN) (REX STOUT)) (((MOBY DICK) (HERMAN MELVILLE) (FICTION)) ((TOM SAWYER) (MARK TWAIN) (FICTION)) ((THE BLACK ORCHID) (REX STOUT) (FICTION MYSTERY))) ------------------------------------------------------------------------------ Recursive Procedures Can Transform and Filter (defun list-authors (books) (if (endp books) ;Is list empty? nil ;If so, return empty list. (cons (book-author (first books)) ;Add author of first book. (list-authors (rest books))))) * (list-authors books) ((PATRICK HENRY WINSTON) (GUY L STEELE) (HENRY MELVILLE) (MARK TWAIN) (REX STOUT)) (defun fictionp (book) (member 'fiction (book-classification book))) * (fictionp '((title (tom sawyer)) (author (mark twain)) (classification (fiction)))) (FICTION) * (fictionp '((title (common lisp)) (author (guy l steele)) (classification (technical list)))) NIL (defun list-fiction-books (books) (cond ((endp books) nil) ;Empty list? ((fictionp (first books)) ;It's fiction, keep it. (cond (first books) (list-fiction-books (rest books)))) (t (list-fiction-books (rest books))))) ;It's not; omit it. * (list-fiction-books books) (((TITLE (MOBY DICK)) (AUTHOR (HERMAN MELVILLE)) (CLASSIFICATION (FICTION))) ((TITLE (TOM SAWYER)) (AUTHOR (MARK TWAIN)) (CLASSIFICATION (FICTION))) ((TITLE (THE BLACK ORCHID)) (AUTHOR (REX STOUT)) (CLASSIFICATION (FICTION MYSTERY)))) ------------------------------------------------------ Recursive Procedures Can Count and Find * (length (list-fiction-books books)) 3 * (first (list-fiction-books books)) ((TITLE (MOBY DICK)) (AUTHOR (HERMAN MELVILLE)) (CLASSIFICATION (FICTION))) (defun count-fiction-books (books) (cond ((endp books) 0) ;Empty list? ((fictionp (first books)) ;It's fiction; count it. (+ 1 (count-fiction-books (rest books)))) (t (count-fiction-books (rest books))))) (defun find-fiction-books (books) (cond ((endp books) nil) ;Empty list? ((fictionp (first books)) ;It's fiction; report it. (first books)) (t (find-fiction-books (rest books))))) 題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題 6-1: Suppose that the arguments to FIND-BOOK-BY-TITLE-WORDS are words that may appear in book titles. FIND-BOOK-BY-TITLE-WORDS is to return the first book it finds that has all of those words in its title: * (find-book-by-title-words '(orchid) books) ((TITLE (THE BLACK ORCHID)) (AUTHOR (REX STOUT)) (CLASSIFICATION (FICTION MYSTERY))) * (find-book-by-title-words '(black orchid) books) ((TITLE (THE BLACK ORCHID)) (AUTHOR (REX STOUT) (CLASSIFICATION (FICTION MYSTERY))) * (find-book-by-title-words '(orchid black) books) ((TITLE (THE BLACK ORCHID)) (AUTHOR (REX STOUT)) (CLASSIFICATION (FICTION MYSTERY))) * (find-book-by-title-words '(blue orchid) books) NIL To define FIND-BOOK-BY-TITLE-WORDS, we need a procedure that matches words to titles. The primitive Lisp procedure SUBSTEP is just right: * (subsetp '(black orchid) '(the black orchid)) T * (substep '(orchid) '(common lisp)) NIL Note, incidentally, that SUBSTEP is indifferent to element order: * (substep '(orchid black) '(the black orchid)) T Using SUBSTEP, define FIND-BOOK-BY-TITLE-WORDS. -------------------------------------------------------------- Cliche Embody Important Programming Knowledge (defun <transforming procedure> (input-list) (if (endp input-list) ;Is list empty? nil (cons (<element transformer> (first input-list)) ;Transform. (<transforming procedure> (rest input-list))))) ;Recurse <transforming procedure> ---> list-authors <element transformer> ---> book-author (defun <filtering procedure> (input-list) (cond ((endp input-list) nil) ((<element tester> (first input-list)) (cons (first input-list) (<filtering procedure> (rest input-list)))) (t (<filtering procedure> (rest input-list))))) (defun <counting procedure> (input-list) (cond ((endp input-list) nil) ((<element tester> (first input-list)) (+ 1 (<counting procedure> (rest input-list)))) (t (<counting procedure> (rest input-list))))) (defun <finding procedure> (input-list) (cond ((endp input-list) nil) ((<element tester> (first input-list)) (first input-list)) (t (<finding procedure> (rest input-list))))) -------------------------------------------------------------- MAPCAR Simplifies Transforming Operations * (mapcar #'oddp ;Procedure object to work with. '(1 2 3)) ;Elements to be fed to the procedure. (T NIL T) * (mapcar #'= '(1 2 3) '(3 2 1)) (NIL T NIL) * (list-authors books) ((PATRICK HENRY WINSTON) (GUY L STEELE) (HERMAN MELVILLE) (MARK TWAIN) (REX STOUT)) * (mapcar #'book-author books) ((PATRICK HENRY WINSTON) (GUY L STEELE) (HERMAN MELVILLE) (MARK TWAIN) (REX STOUT)) --------------------------------------------------------- REMOVE-IF and REMOVE-IF-NOT Simplify Filtering Operations * (remove-if-not #'fictionp books) (((TITLE (MOBY DICK)) (AUTHOR (HERMAN MELVILLE)) (CLASSIFICATION (FICTION))) ((TITLE (TOM SAWYER)) (AUTHOR (MARK TWAIN)) (CLASSIFICATION (FICTION))) (TITLE (THE BLACK ORCHID)) (AUTHOR (REX STOUT)) (CLASSIFICATION (FICTION MYSTERY)))) * (remove-if #'fictionp books) (((TITLE (ARTIFICIAL INTELLIGENCE)) (AUTHOR (PATRICK HENRY WINSTON)) (CLASSIFICATION (TECHNICAL AI))) ((TITLE (COMMON LISP)) (AUTHOR (GUY L STEELE)) (CLASSIFICATION (TECHNICAL LIST)))) ---------------------------------------------- COUNT-IF and FIND-IF Simplify Counting and Finding Operations * (count-if #'fictionp books) 3 * (find-if #'fictionp books) ((TITLE (MOBY DICK)) (AUTHOR (HERMAN MELVILLE)) (CLASSIFICATION (FICTION))) ------------------------------------------------- FUNCALL and APPLY Also Take a Procedure Argument (funcall #'<procedure specification> <argument 1> ... <argument N>) (funcall #'first '(e1 e2 e3)) (first '(e1 e2 e3)) (funcall #'append '(a b) '(x y)) (append '(a b) '(x y)) * (toss '(victim of attack) #'first) VICTIM * (toss '(victim of attack) #'rest) (OF ATTACK) (defun toss (argument procedure) (funcall procedure argument)) (defun toss (argument procedure) ;Bugged! (Procedure argument)) ;Bugged! (apply #'<procedure name> <list of arguments>) (apply #'first '((e1 e2 e3))) (first '(e1 e2 e3)) (apply #'append '((a b) (x y))) (append '(a b) '(x y)) (funcall #'<procedure name> <argument 1> ... <argument N>) (apply #'<procedure name> <list of arguments>) (apply #'+ '(1 2 3 4 5 6)) ;Argument list fed to + is (1 2 3 4 5 6) (apply #'+ 1 2 3 '(4 5 6)) ;Argument list fed to + is (append (list 1 2 3) '(4 5 6)) (defun toss (argument procedure) (apply procedure (list argument))) ----------------------------------------------------------- LAMBDA Defines Anonymous Procedures (defun book-last-name (book) (first (last (book-author book)))) * (mapcar #'book-last-name books) (WINSTON STEELE MELVILLE TWAIN STOUT) (defun book-last-name (book) (first (last (book-author book)))) (lambda (book) (first (last (book-author book)))) * (mapcar #'book-last-name books) * (mapcar #'(lambda (book) (first (last (book-author book)))) books) * (mapcar #'book-last-name books) (WINSTON STEELE MELVILLE TWAIN STOUT) * (mapcar #'(lambda (book) (first (last (book-author book)))) books) (WINSTON STEELE MELVILLE TWAIN STOUT) * (remove-if-not #'(lambda (book) (member 'fiction (book-classification book))) books) (((TITLE (MOBY DICK)) (AUTHOR (HERMAN MELVILLE)) (CLASSIFICATION (FICTION))) ((TITLE (TOM SAWYER)) (AUTHOR (MARK TWAIN)) (CLASSIFICATION (FICTION))) (TITLE (THE BLACK ORCHID)) (AUTHOR (REX STOUT)) (CLASSIFICATION (FICTION MYSTERY)))) * (funcall #'(lambda (parameter) (first parameter)) '(e1 e2 e3)) E1 * (apply #'(lambda (parameter1 parameter2) (append parameter1 parameter2)) '((a b) (x y))) (A B X Y) 解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解 6-1: (defun find-book-by-title-words (title-words books) (cond ((endp books) nil) ((substep title-words (book-title (first books))) (first books)) (t (find-book-by-title-words title-words (rest books)))))