250 likes | 359 Views
66-2210-01 Programming in Lisp. Data Abstraction and Mapping. Data Representation. Record course information Basic definition (setf course-1 '(66221001 ; course number (Programming in Lisp) ; course name (Alok Mehta) ; instructor (Computer Science))) ; department
E N D
66-2210-01 Programming in Lisp Data Abstraction and Mapping Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Data Representation • Record course information • Basic definition • (setf course-1 '(66221001 ; course number • (Programming in Lisp) ; course name • (Alok Mehta) ; instructor • (Computer Science))) ; department • What is the name of ‘course-1’? • > (second course-1) • (Programming in Lisp) • Poor practice - Depends on the ordering of the list • What if order changes, or, you need to add something to the list • (setf course-1 '(66221001 • 1 ; Credit hours • (Programming in Lisp) ; Course name • (Alok Mehta) ; Instructor • (Computer Science))) ; Department • All programs that access name of course-1 have to change • > (third course-1) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Association Lists • How do you know ‘1’ represents credit hours? • Better way to represent data: Association Lists • (setf course-1 '( • (course-number 66221001) • (credit-hours 1) • (name (Programming in Lisp)) • (instructor (Alok Mehta)) • (department (Computer Science)))) • What is the name of ‘course-1’? • > (second (third course-1)) • (PROGRAMMING IN LISP) • > (assoc 'name course-1) • (NAME (PROGRAMMING IN LISP)) • > (second (assoc 'name course-1) • (PROGRAMMING IN LISP) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Simple Database • A database as a list of “records” • (setf course-database '( • ((course-number 66221001) • (credit-hours 1) • (name (Programming in Lisp)) • (instructor (Alok Mehta)) • (department (Computer Science))) • ((course-number 66220001) • (credit-hours 1) • (name (Programming in C++)) • (instructor (Louis Ziantz))) • )) • What is the name? • (second (assoc 'name (first course-database))) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Access Functions • Write functions to access low-level details • (defun get-course-name (course) • (second (assoc 'name course))) • Don’t have to remember how data is stored • Can change storage details easily • Access to data is achieved at a higher level • Easier to read and understand • More maintainable code • Write functions to construct and manipulate data • (defun make-course (&key course-number credit-hours • name instructor department) • (list (list 'course-number course-number) • (list 'credit-hours credit-hours) • (list 'name name) • (list 'instructor instructor) • (list 'department department) • )) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Calling Access Functions • > (setf course-1 (make-course • :name '(Programming in Java) • :instructor ’(Alok Mehta))) • ((COURSE-NUMBER NIL) • (CREDIT-HOURS NIL) • (NAME (PROGRAMMING IN JAVA)) • (INSTRUCTOR (ALOK MEHTA)) • (DEPARTMENT NIL)) • > (get-course-name course-1) • (PROGRAMMING IN JAVA) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
A simple database example • (setf courses (list • (make-course :course-number '66220001 • :name '(Programming in C++) • :instructor '(Louis Ziantz)) • (make-course :course-number '66221001 • :name '(Programming in Lisp) • :instructor '(Alok Mehta)) • (make-course :course-number '66222001 • :name '(Programming in Java) • :instructor '(Alok Mehta)) • (make-course :course-number '66223001 • :name '(Programming in Perl) • :instructor '(Louis Ziantz)) • )) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Which courses are offered? • Example Usage • > (get-course-numbers courses) • (66220001 66221001 66222001 66223001) • (defun get-course-number (course) • (second (assoc 'course-number course))) • (defun get-course-numbers (course-list) • (if (endp course-list) • NIL • (cons (get-course-number (first course-list)) • (get-course-numbers (rest course-list))))) • Implements a “Transformation” • SQL Equivalent: • SELECT course_number • FROM courses; Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Which are taught by Alok? • List the courses taught by Alok Mehta • > (get-courses-taught-by-alok courses) • (((COURSE-NUMBER 66221001) …) ((COURSE-NUMBER 66222001) ...) ...) • (defun get-course-instructor (course) • (second (assoc 'instructor course))) • (defun taught-by-alok-p (course) • (if (equal '(Alok Mehta) (get-course-instructor course)) • t • NIL)) • (defun get-courses-taught-by-alok (course-list) • (cond • ((endp course-list) NIL) • ((taught-by-alok-p (first course-list)) • (cons (first course-list) • (get-courses-taught-by-alok (rest course-list)))) • (t (get-courses-taught-by-alok (rest course-list))))) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
How many are taught by Alok • List the courses taught by Alok Mehta [Filter] • > (get-courses-taught-by-alok courses) • Implements “Filtering” • SQL: SELECT * FROM COURSES • WHERE instructor = ‘Alok Mehta’; • How many courses are taught by Alok? [Count] • > (length (get-courses-taught-by-alok courses)) • 2 • SQL: SELECT COUNT(*) FROM COURSES • WHERE instructor = ‘Alok Mehta’; • What is the first course taught by Alok? [Find] • > (first (get-courses-taught-by-alok courses)) • ((COURSE-NUMBER 66221001) • (CREDIT-HOURS NIL) • (NAME (PROGRAMMING IN LISP)) • (INSTRUCTOR (ALOK MEHTA)) • (DEPARTMENT NIL)) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
More efficient way to Count • A more efficient way to count • Don’t have to get all courses first! • (defun count-courses-taught-by-alok (course-list) • (cond ((endp course-list) 0) • ((taught-by-alok-p (first course-list)) • (+ 1 (count-courses-taught-by-alok • (rest course-list)))) • (t (count-courses-taught-by-alok • (rest course-list))))) • A more efficient way to find first course • (defun find-first-course-taught-by-alok (course-list) • (cond ((endp course-list) nil) • ((taught-by-alok-p (first course-list)) • (first course-list)) • (t (find-first-course-taught-by-alok • (rest course-list))))) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Cliches • Many procedures have a common template • (defun <list-transformer> (input-list) • (if (endp input-list) • nil • (cons (<element-transformer> (first input-list)) • (<list-transformer> (rest input-list))))) • Example: • List-transformer: get-course-numbers • Element-transformer: get-course-number • (defun get-course-numbers (course-list) • (if (endp course-list) • NIL • (cons (get-course-number (first course-list)) • (get-course-numbers (rest course-list))))) • This template is frequently used • Lisp has a primitive (MAPCAR) to make this easier Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Mapcar • MAPCAR • (mapcar <procedure> <argument>) • Applies <procedure> to each element of <argument> • Example • > (mapcar #'oddp '(1 2 3)) • (T NIL T) • > (mapcar #'get-course-number courses) • (66220001 66221001 66222001 66223001) • > (mapcar #'= '(1 2 3) '(3 2 1)) • (NIL T NIL) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Remove-If, Remove-If-Not • Remove-If, Remove-If-Not • > (remove-if-not #'taught-by-alok-p courses) • [Removes all courses for which “taught-by-alok-p” returns NIL] • This will return all courses taught by Alok • > (remove-if #'taught-by-alok-p courses) • [Removes all courses for which “taught-by-alok-p” returns non-NIL] • This will return all courses NOT taught by Alok • Count-If, Count-If-Not • > (count-if #'taught-by-alok-p courses) • Counts the number of elements for which “taught-by-alok-p” returns non-NIL • Find-If, Find-If-Not • > (find-if #'taught-by-alok-p courses) • Returns the FIRST element of courses for which “taught-by-alok-p” returns non-NIL Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Funcall • Funcall • Template • (funcall #'<procedure> <arg1> … <argN>) • Calls the specified procedure with the given argments • Equivalent to • (<procedure> <arg1> … <argN>) • Example • > (funcall #'+ 3 2 7) ;; Same as (+ 3 2 7) • 12 • Example 2 • > (defun eval-infix (arg1 operator arg2) • (funcall operator arg1 arg2)) • > (eval-infix 3 #'+ 2) • Useful if you need to pass in a procedure name, to be applied at a future time Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Apply • Apply • Similar to Funcall • (typically) takes two arguments, • procedure object • list of arguments to be passed to procedure object • (funcall #'+ 3 2 7) ;; Same as (+ 3 2 7) • (apply #'+ '(3 2 7)) ;; Same as (+ 3 2 7) • Apply can actually take additional arguments • Extra arguments are combined into a single list • Following are equivalent • (apply #'+ '(1 2 3 4 5 6)) • (apply #'+ 1 2 3 '(4 5 6)) • Argument fed to + is (append (list 1 2 3) ‘(4 5 6)) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Lambda Procedures • Useful if you need an “anonymous” procedure • Don’t want to give it a name • A named procedure • (defun taught-by-alok-p (course) • (if (equal '(Alok Mehta) (get-course-instructor course)) • t • NIL)) • An equivalent un-named procedure • (lambda (course) • (if (equal '(Alok Mehta) (get-course-instructor course)) • t • NIL)) • Example usage: How many courses are taught by Alok? • (count-if #'(lambda (course) • (if (equal '(Alok Mehta) • (get-course-instructor course)) • t • NIL)) • courses) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Lambda procedures • Advantage • Don’t have to make up names for procedures • Definition of procedure is close to where it is used • (defun get-courses-taught-by-alok (course-list) • (remove-if-not • #'(lambda (x) • (equal '(Alok Mehta) (get-course-instructor x))) • course-list)) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Summary • Use readers, constructors, and writers • To hide data details • Transform, Filter, Count, Find are common • Can be defined recursively • Built-in functions in Lisp make things easier • Mapcar, Remove-If(Not), Count-If(Not), Find-If(Not) • Funcall, Apply • Lambda Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Iteration • DOTIMES (Review) • (dotimes (<counter> <upper-bound> <final-result>) • <body>) • Example • (dotimes (i 5) (print i)) ;; prints 0 1 2 3 4 • DOLIST • (dolist (<element> <list-of-elements> <final-result>) • <body>) • Example • (dolist (elem '(a b c d)) (print elem)) ;; prints a b c d Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Example of DOLIST • Given a list of ages of people, how many adults? • List of ages • > (setf ages '(3 4 17 21 22 34 2 7)) • Adult defined as: >= 21 years old • > (defun adultp (age) (>= age 21)) • Using Count-if • (defun count-adult (ages) (count-if #'adultp ages)) • Using dolist • (defun count-adult (ages &aux (nadult 0)) • (dolist (age ages nadult) • (if (adultp age) (setf nadult (+ 1 nadult))))) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Example (cont.) • Get the ages of the first two adults • (defun first-two-adults (ages &aux (nadult 0) (adults nil)) • (dolist (age ages) • (if (adultp age) • (progn (setf nadult (+ nadult 1)) • (push age adults) • (if (= nadult 2) (return adults)))))) • Notes • PROGN (and PROG1) are like C/C++ Blocks { … } • > (prog1 (setf a 'x) (setf b 'y) (setf c 'z)) • X • > (progn (setf a 'x) (setf b 'y) (setf c 'z)) • Z • RETURN exits the DOLIST block • Note: does not necessarily return from the procedure! • Takes an optional return value Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
DO • DO is more general than DOLIST or DOTIMES • Example • (defun do-expt (m n) ;; Return M^N • (do ((result 1) ;; Bind variable ‘Result’ to 1 • (exponent n)) ;; Bind variable ‘Exponent’ to N • ((zerop exponent) result) ;; test and return value • (setf result (* m result)) ;; Body • (setf exponent (- exponent 1)) ;; Body • Equivalent C/C++ definition • int do_expt (int m, int n) { • int result, exponent; • for (result=1,exponent=n; (exponent != 0); ) { • result = m * result; • exponent = exponent - 1; • } • return result; • } Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
DO Template • Full DO Template (There is also a DO*) • (DO ( (<p1> <i1> <u1>) • (<p2> <i2> <u2>) … • (<pN> <iN> <uN>) ) • ( <term-test> • <a1> <a2> … <aN> • <result> ) • <body> ) • Rough equivalent in C/C++ • for ( <p1>=<i1>, <p2>=<i2>,…,<pN>=<iN>; //Note: Lisp=parallel • !(<term-test>); // C/C++ has a “continuation-test” • <p1>=<u1>, <p2>=<u2>,…,<pN>=<uN>) { • <body> • } • <a1>; <a2>; … ; <aN>; • <result>; // Note: (DO…) in Lisp evaluates to <result> • // Note: <p1>,<p2>,…,<pN> are now restored to original values Alok Mehta - Programming in Lisp - Data Abstraction and Mapping
Do-expt, Loop • Here is another (equivalent) definition of do-expt • (defun do-expt (m n) • (do ((result 1 (* m result)) • (exponent n (- exponent 1))) • ((zerop exponent) result) • ;; Note that there is no body! • )) • Loop • An infinite loop, terminated only by a (return) • (loop • (print '(Say uncle)) • (if (equal (read) 'uncle) (return))) Alok Mehta - Programming in Lisp - Data Abstraction and Mapping