25
Alok Mehta - Programming in Lisp - Data Abstraction and Mapping 1 66-2210-01 Programming in Lisp Data Abstraction and Mapping

Alok Mehta - Programming in Lisp - Data Abstraction and Mapping 1 66-2210-01 Programming in Lisp Data Abstraction and Mapping

Embed Size (px)

Citation preview

Alok Mehta - Programming in Lisp - Data Abstraction and Mapping 1

66-2210-01 Programming in Lisp

Data Abstraction and Mapping

Alok Mehta - Programming in Lisp - Data Abstraction and Mapping 2

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 3

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 4

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 5

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 6

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 7

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))))

Course Name Instructor Credit Hours Department66220001 Programming in C++ Louis Ziantz66221001 Programming in Lisp Alok Mehta66222001 Programming in Java Alok Mehta66223001 Programming in Perl Louis Ziantz

Alok Mehta - Programming in Lisp - Data Abstraction and Mapping 8

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 9

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 10

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)) 2SQL: 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 11

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 12

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 13

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 14

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 15

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 16

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 17

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 18

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 19

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 20

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 21

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 22

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 23

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++ definitionint 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 24

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 25

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)))