List manipulation Consider student database, where each student is represented by the following list: * (setf student1 '((Paul Bennett) ((hw1 4.3) (hw2.

Slides:



Advertisements
Similar presentations
09 Examples Functional Programming. Tower of Hanoi AB C.
Advertisements

CS 63 LISP Philip Greenspun's Tenth* Rule of Programming:
ANSI Common Lisp 3. Lists 20 June Lists Conses List Functions Trees Sets Stacks Dotted Lists Assoc-lists.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
1 Programming Languages and Paradigms Lisp Programming.
CSE 341 Lecture 16 More Scheme: lists; helpers; let/let*; higher-order functions; lambdas slides created by Marty Stepp
List manipulation Consider student database, where each student is represented by the following list: * (setf student1 '((Paul Bennett) ((hw1 4.3) (hw2.
Higher Order Functions “I hope you’re convinced, by now, that programming languages with first-class functions let you find more opportunities for abstraction,
Lisp – Introduction יעל נצר מערכות נבונות סמסטר ב' תשס"ו.
Functional Programming COMP2003 A course on functional programming using Common Lisp Dr Eleni Mangina
Introduction to Artificial Intelligence Lisp Ruth Bergman Fall 2002.
First Lecture on Introductory Lisp Yun Peng. Why Lisp? Because it’s the most widely used AI programming language Because AI researchers and theoreticians.
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site).
LISP primitives on sequences FIRST (or CAR) and REST (or CDR) take lists apart. Consider the list (First day of the semester). * (first '(First day of.
Returning values from functions You can return a value from a function by using the built- in function : ( return-from Function_name value) For example:
CMSC 471 LISP. Why Lisp? Because it’s the most widely used AI programming language Because it’s good for writing production software (Graham article)
CSE S. Tanimoto Explicit Function Application 1 Explicit Application of Functions, Functional Arguments and Explicit Evaluation Implicit and explicit.
Mapping And Iteration So far, the only Lisp mechanism we have considered, which allows an action to be performed repeatedly is recursion. Most programming.
Programming in Lisp; Instructor: Alok Mehta Programming in Lisp Recursion, Data Abstraction, Mapping, Iteration.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
LISP A brief overview. Lisp stands for “LISt Process” –Invented by John McCarthy (1958) –Simple data structure (atoms and lists) –Heavy use of recursion.
LISP 1.5 and beyond A very quick tour. Data Atoms (symbols) including numbers – All types of numbers including Roman! (well, in the early days) – Syntactically.
F UNCTIONAL P ROGRAMMING 05 Functions. F UNCTIONS - G LOBAL F UNCTIONS fboundp Tells whether there is a function with a given symbol as its name > (fboundp.
Yu-Tzu Lin ( 林育慈 )
Advanced Functions In CL, functions are often supplied as parameters to other functions –This gives us tremendous flexibility in writing functions whose.
For Wednesday Read Chapter 4, sections 1 and 2 Homework: –Lisp handout 3.
Functional Programming 02 Lists
Alok Mehta - Programming in Lisp - Data Abstraction and Mapping Programming in Lisp Data Abstraction and Mapping.
The Case primitive: matches the evaluated key form against the unevaluated keys by using eql The general format of case is the following: (case (... ).....
Mitthögskolan 10/8/ Common Lisp LISTS. Mitthögskolan 10/8/2015 2Lists n Lists are one of the fundamental data structures in Lisp. n However, it.
For Monday Read Chapter 3 Homework: –Lisp handout 2.
Common lisp A functional programming language. Useful URL:
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
CSCI 2210: Programming in Lisp
LISP Data Types Functional Programming Academic Year Alessandro Cimatti
Building user-defined functions: the progressive envelopment technique The idea: define combinations of LISP primitives through a sequence of experiments.
Introduction to LISP. Lisp Extensible: It lets you define new operators yourself Lisp programs are expressed as lisp data structures –You can write programs.
UMBC CMSC Common Lisp II. UMBC CMSC Input and Output Print is the most primitive output function > (print (list 'foo 'bar)) (FOO BAR) The.
Procedures with optional parameters which do not require matching arguments Example: consider the exponent function which may take one argument, m, in.
Control in LISP More on Predicates & Conditionals.
Operating on Lists Chapter 6. Firsts and Seconds n Transforming list of pairs into two lists –(firsts ‘((1 5) (2 6) (3 7)))  (1 2 3) –(seconds ‘((1 5)
Milos Hauskrecht (PDF) Hieu D. Vu (PPT) LISP PROGARMMING LANGUAGE.
Search as a problem solving technique. Consider an AI program that is capable of formulating a desired goal based on the analysis of the current world.
Functional Programming: Lisp MacLennan Chapter 10.
Comparative Programming Languages Functional programming with Lisp/Scheme.
Ch Ch jcmt CSE 3302 Programming Languages CSE3302 Programming Languages (n-n-n-notes) Summer 2003 Dr. Carter Tiernan.
1 Outline Review Introduction to LISP Symbols and Numbers Lists Writing LISP Functions LISPWorks.
Section 15.4, 15.6 plus other materials
LISP – (LISt Processing)
Example of formula (defun roots (a b c) (list
Pairs and Lists. Data Abstraction. SICP: Sections – 2.2.1
LISP A brief overview.
6.001 SICP Data abstractions
First Lecture on Introductory Lisp
J.E. Spragg Mitthögskolan 1997
Modern Programming Languages Lecture 21 Fakhar Lodhi
Dynamic Scoping Lazy Evaluation
CSE S. Tanimoto Explicit Function Application
Lisp: Using Functions as Data
LISP A brief overview.
List and list operations (continue).
Abstraction and Repetition
Functional Programming: Lisp
Lisp: Using Functions as Data
Common Lisp II.
Programming Languages
The general format of case is the following: (case <key form>
LISP primitives on sequences
Procedures with optional parameters which do not require matching arguments Example: consider the exponent function which may take one argument, m, in.
Presentation transcript:

List manipulation Consider student database, where each student is represented by the following list: * (setf student1 '((Paul Bennett) ((hw1 4.3) (hw2 5.0) (hw3 3.5) (hw4 4.8) (hw5 4.9)) ((test1 9.5) (test2 8.7)) (classw 10.0) (project 18) (final 28))) Given this representation, to find HW2 grade of student1: * (second (second (second student1))) ==> 5.0 To add student major as a second element of student list: (setf student1 (append (list (first student1)) (list '(CS major)) (rest student1))) ((PAUL BENNETT) (CS MAJOR) ((HW1 4.3) (HW2 5.0) (HW3 3.5) (HW4 4.8) (HW5 4.9)) ((TEST1 9.5) (TEST2 8.7)) (CLASSW 10.0) (PROJECT 18) (FINAL 28)) Now to get to student1 HW2 grade, a different reader procedure must be used: * (second (second (third student1))) That is, any change in the data representation requires a change in the “getter” procedure. Furthermore, all of the details of the data representation must be remembered in order to construct an appropriate “getter”.

Better representation for student database example. Consider the following association lists for representing students: ((name (Paul Bennett)) ((name (Abe Cadman)) (major CS) (major CS) (homeworks (4.3 5.0 3.5 4.8 4.9)) (status withdrawn)) (tests (9.5 8.7)) (claswork 10.0) (project 18) (final 28)) The following procedure will construct each of these a-lists: (defun construct-student (name major hw1 &optional hw2 hw3 hw4 hw5 test1 test2 classwork project final) (if (eql hw1 'withdrawn) (list (list 'name name) (list 'major major) (list 'status 'withdrawn)) (list (list 'name name) (list 'major major) (list 'homeworks (list hw1 hw2 hw3 hw4 hw5)) (list 'tests (list test1 test2)) (list 'classwork classwork) (list 'project project) (list 'final final)))) To construct student1 and student2: * (setf student1 (construct-student '(Paul Bennett) 'CS 4.3 5.0 3.5 4.8 4.9 9.5 8.7 10.0 18 28)) ((NAME (PAUL BENNETT)) (MAJOR CS) (HOMEWORKS (4.3 5.0 3.5 4.8 4.9)) (TESTS (9.5 8.7)) (CLASSWORK 10.0) (PROJECT 18) (FINAL 28)) * (setf student2 (construct-student '(Abe Cadman) 'CS 'withdrawn)) ((NAME (ABE CADMAN)) (MAJOR CS) (STATUS WITHDRAWN))

Example (cont.) We can now create “getter” procedures to access each one of the elements of student1. For example, to access the grade for HW2: (defun get-hw2 (student) (if (eql (second (assoc 'status student)) 'withdrawn) 'withdrawn (second (second (assoc 'homeworks student))))) Once constructor and getter procedures are defined, we can forget the details of the representation. If the representation changes, only affected procedures must be re-written. To set-up the student database: (setf students (list (construct-student '(Paul Bennett) 'CS 4.3 5.0 3.5 4.8 4.9 9.5 8.7 10.0 18 28) (construct-student '(Abe Cadman) 'CS 'withdrawn) (construct-student '(Nelson DaCunha) 'CS 4.8 4.0 4.5 3.8 5.0 8.5 9.7 10.0 17 25) (construct-student '(Susan Melville) 'CS 3.8 5.0 4.7 4.8 5.0 8.3 9.9 10.0 20 24) (construct-student '(Igor Pevac) 'CS 'withdrawn)))

List transformation: returns a list containing only selected elements of the original list Example: Transform the students list into a list containing only student names. (defun names (students) (if (endp students) nil (cons (get-name (first students)) (names (rest students))))) (defun get-name (student) (second (assoc 'name student))) * students (((NAME (PAUL BENNETT)) (MAJOR CS) (HOMEWORKS (4.3 5.0 3.5 4.8 4.9)) (TESTS (9.5 8.7)) (CLASSWORK 10.0) (PROJECT 18) (FINAL 28)) ((NAME (ABE CADMAN)) (MAJOR CS) (STATUS WITHDRAWN)) ((NAME (NELSON DACUNHA)) (MAJOR CS) (HOMEWORKS (4.8 4.0 4.5 3.8 5.0)) (TESTS (8.5 9.7)) (CLASSWORK 10.0) (PROJECT 17) (FINAL 25)) ((NAME (SUSAN MELVILLE)) (MAJOR CS) (HOMEWORKS (3.8 5.0 4.7 4.8 5.0)) (TESTS (8.3 9.9)) (CLASSWORK 10.0) (PROJECT 20) (FINAL 24)) ((NAME (IGOR PEVAC)) (MAJOR CS) (STATUS WITHDRAWN))) * (names students) ((PAUL BENNETT) (ABE CADMAN) (NELSON DACUNHA) (SUSAN MELVILLE) (IGOR PEVAC))

List transformation procedures: a general format When transforming a list into another list, the resulting list is of the same length as the original list. The general format of the transformation procedure is the following: (defun <transformation-proc> (list-1) (if (endp list-1) NIL (cons (<get-desired-element-proc> (first list-1)) (<transformation-proc> (rest list-1)))))

The MAPCAR primitive transforms lists Mapcar has the following format: (mapcar #’<procedure object> <list-1> ...<list-n> ), where: <procedure object> supplies the name of the transforming procedure, <list-1>,..., <list-n> supply lists of elements to be transformed. Examples: * (mapcar #'zerop '(8 5 0 1 0 5)) (NIL NIL T NIL T NIL) * (mapcar #'= '(1 2 3 4 5) '(1 3 5 4 8)) (T NIL NIL T NIL) * (mapcar #'get-name students) ((PAUL BENNETT) (ABE CADMAN) (NELSON DACUNHA) (SUSAN MELVILLE) (IGOR PEVAC)) * (mapcar #'get-hw2 students) (5.0 WITHDRAWN 4.0 5.0 WITHDRAWN)

Filtering undesired elements Consider the list (5.0 WITHDRAWN 4.0 5.0 WITHDRAWN). To compute the average grade, we must filter non-numerical atoms. (defun clean-grade-list (grade-list) (cond ((endp grade-list) nil) ((numberp (first grade-list)) (cons (first grade-list) (clean-grade-list (rest grade-list)))) (t (clean-grade-list (rest grade-list))))) * (clean-grade-list (mapcar #'get-hw2 students)) (5.0 4.0 5.0)

Filtering procedures: a general format Procedures for filtering out elements that do not satisfy the desired property have the following general format: (defun <filtering-procedure> (list-1) (cond ((endp <list-1>) nil) ((<testing-for-desired-property-proc> (first list-1)) (cons (first list-1) (filtering-procedure> (rest list-1)))) (t (filtering-procedure> (rest list-1)))) The resulting list may contain the same or smaller number of elements than the original list.

The REMOVE-IF and REMOVE-IF-NOT primitives simplify filtering procedures Remove-if removes all elements of list, which satisfy the predicate serving as a filter. Its general format is the following: (remove-if #’<procedure object> <list>) Remove-if-not removes all elements of list, which do not satisfy the predicate serving as a filter. Its general format is the following: (remove-if-not #’<procedure object> <list>) where: <procedure object> supplies the name of the filtering procedure, <list> is the list of elements to be filtered.

Examples: To filter all symbols (non-numerical atoms) from the grades list: * (remove-if # 'symbolp (mapcar #'get-hw2 students)) (5.0 4.0 5.0) Or, also we can say * (remove-if-not #'numberp (mapcar #'get-hw2 students)) Filter zeros from a given list of numbers: * (remove-if #'zerop '(2 0 4 6 0 0)) (2 4 6) Filter non-even elements of a given list of numbers: * (remove-if-not #'evenp '(3 4 5 6 7 8)) (4 6 8)

Mapping primitives can take as a procedure object an already defined function or a lambda expression Lambda expressions are “anonymous” functions. Example: compute the square of m * #'(lambda (n) (* n n)) #<LISP::SCANNED (LAMBDA (N) (DECLARE) (* N N))> * (setf square #'(lambda (n) (* n n))) * square * (mapcar square '(1 2 3 4 5)) (1 4 9 16 25) * (mapcar #'(lambda (n) (* n n)) '(1 2 3 4 5)) Lambda expressions make it possible to create new functions at run time. Such run-time functions are called closures.

Counting list elements that satisfy a desired property Consider the student DB example, and assume that we want to count students that have withdrawn from the class. The following function will do the job: (defun count-w (students) (cond ((endp students) 0) ((eql (second (assoc 'status (first students))) 'withdrawn) (+ 1 (count-w (rest students)))) (t (count-w (rest students))))) The general format of any counting procedure is: (defun <counting proc> (list-1) (cond ((endp list-1) 0) ((<testing-desired-prop proc> (first list-1)) (+ 1 (<counting proc> (rest list-1)))) (t (<counting proc> (rest list-1)))))

The COUNT-IF and COUNT-IF-NOT primitives To count the number of students that have withdrawn, we can also say: * (count-if #'(lambda (student) (eql (second (assoc 'status student)) 'withdrawn)) students) 2 Or, if we have defined predicate get-w (defun get-w (student) (eql (second (assoc 'status student)) 'withdrawn)) the equivalent query is: * (count-if #'get-w students) To count the number of students that have not withdrawn: * (count-if-not #'get-w students) 3

COUNT-IF counts the number of elements on a list that satisfy a given property; EVERY / SOME test if every / some element on the list satisfies a given property Examples: * (count-if #'oddp '(1 2 3 4 5)) 3 * (every #'oddp '(1 2 3 4 5)) NIL * (some #'oddp '(1 2 3 4 5)) T

Searching for an element that satisfies a desired property Assume we want to search for a student who have 20 points on the project. The following functions will do the job: (defun search-project-20 (students) (cond ((endp students) nil) ((eql 20 (get-project (first students))) (second (assoc 'name (first students)))) (t (search-project-20 (rest students))))) (defun get-project (student) (second (assoc 'project student))) * (search-project-20 students) (SUSAN MELVILLE)

General format of a searching procedure and its substitute primitives FIND-IF and FIND-IF-NOT (defun <searching procedure> (list-1) (cond ((endp list-1) nil) ((<testing-desired-prop proc> (first list-1)) (first list-1)) (t (<searching procedure> (rest list-1))))) Find-if and find-if-not are primitives that search for the first element of a list satisfying (not satisfying) a desired property. In the student DB example, to ask if at least one student has (has not) 20 points on the project, we can say: * (second (assoc 'name (find-if #'(lambda (student) (eql 20 (get-project student))) students)) ) (SUSAN MELVILLE) * (second (assoc 'name (find-if-not #'(lambda (student) (eql 20 (get-project student))) students))) (PAUL BENNETT)

The FUNCALL and APPLY primitives allow procedures to be passed as arguments The funcall primitive has the following format: (funcall #’<procedure object> <argument-1> ... <argument-n>) The apply primitive has the following format: (apply #’<procedure object> (<argument-1> ... <argument-n>)) Examples: * (defun pass-operator (operand-1 operand-2 operator) (funcall operator operand-1 operand-2)) PASS-OPERATOR * (pass-operator 33 22 '+) 55 * (pass-operator 33 22 '-) 11 * (pass-operator 33 22 '*) 726

Examples (cont.) Notice that without funcall, the pass-operator function will not work: * (defun pass-operator (operand-1 operand-2 operator) (operator operand-1 operand-2)) PASS-OPERATOR * (pass-operator 33 22 '+) *** Debugger warning: leftover specials *** >>> Error: {Determining function in error.} >>> Error:Undefined function: OPERATOR while evaluating: (OPERATOR OPERAND-1 OPERAND-2) The apply primitive can be used instead of funcall as follows: (apply operator (list operand-1 operand-2))) 55 * (pass-operator 33 22 '-) 11

More examples In some cases, apply may have more than two arguments: * (funcall #'first '(a b c d)) A * (funcall #'list 'a 'b 'c 'd) (A B C D) * (funcall #'append '(a b) '(c d)) * (funcall #'+ 1 2 3 '(4 5 6)) *** Debugger warning: leftover specials *** >>> Error: {Determining function in error.} >>> Error:+: wrong type argument: (4 5 6) A NUMBER was expected. * (apply #'first '((a b c d))) A * (apply #'list '(a b c d)) (A B C D) * (apply #'append '((a b) (c d))) In some cases, apply may have more than two arguments: * (apply #'+ 1 2 3 '(4 5 6)) 21