PRACTICAL COMMON LISP Peter Seibel 1.

Slides:



Advertisements
Similar presentations
CS 63 LISP Philip Greenspun's Tenth* Rule of Programming:
Advertisements

ANSI Common Lisp 3. Lists 20 June Lists Conses List Functions Trees Sets Stacks Dotted Lists Assoc-lists.
Lisp. Versions of LISP Lisp is an old language with many variants Lisp is alive and well today Most modern versions are based on Common Lisp LispWorks.
C-LISP. LISP 2 Lisp was invented by John McCarthy in 1958 while he was at the Massachusetts Institute of Technology (MIT).John McCarthyMassachusetts Institute.
Some non-recursive tricks. The Lambda expression. More on Let, Let*, apply and funcall.
Lists in Lisp and Scheme a. Lists are Lisp’s fundamental data structures, but there are others – Arrays, characters, strings, etc. – Common Lisp has moved.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
Lambda Calculus and Lisp PZ03J. Lambda Calculus The lambda calculus is a model for functional programming like Turing machines are models for imperative.
Chapter 3 Functional Programming. Outline Introduction to functional programming Scheme: an untyped functional programming language.
CS 355 – PROGRAMMING LANGUAGES Dr. X. Apply-to-all A functional form that takes a single function as a parameter and yields a list of values obtained.
Lisp – Introduction יעל נצר מערכות נבונות סמסטר ב' תשס"ו.
Lisp Recitation (cse471/598 Fall 2007 ) Aravind Kalavagattu.
ITERATIVE CONSTRUCTS: DOLIST Dolist is an iterative construct (a loop statement) consisting of a variable declaration and a body The body states what happens.
Lisp. Versions of LISP Lisp is an old language with many variants –LISP is an acronym for List Processing language Lisp is alive and well today Most modern.
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.
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)
Introductory Lisp Programming Lecture # 2 Main Topics –Basic Lisp data types –Lisp primitives –Details of list handling Cons cells (boxes) & their representation.
Artificial Intelligence and Lisp Lecture 6 LiU Course TDDC65 Autumn Semester, 2010
Recursion. Definitions I A recursive definition is a definition in which the thing being defined occurs as part of its own definition Example: A list.
General pattern for selecting some elements of a list This negatives example illustrates a general pattern: If you want a function which selects some elements.
COMP 205 – Week 11 Dr. Chunbo Chu. Intro Lisp stands for “LISt Process” Invented by John McCarthy (1958) Simple data structure (atoms and lists) Heavy.
(5.1) COEN Functional Languages  Functional programming basics  Atoms and lists; cons  Useful primitive functions  Predicates  Arithmetic functions.
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.
Advanced Functions In CL, functions are often supplied as parameters to other functions –This gives us tremendous flexibility in writing functions whose.
Functional Programming 02 Lists
PRACTICAL COMMON LISP Peter Seibel 1.
Functional Programming Here we briefly look at what functional programming is and why we want to study it –a function, in the mathematical sense, is a.
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.
1 Lists in Lisp and Scheme. 2 Lists are Lisp’s fundamental data structures. Lists are Lisp’s fundamental data structures. However, it is not the only.
1 Lisp Functions –Built-in functions –Defining functions –Function Evaluation and Special Forms defun, if Control statements –Conditional if, cond –Repetition.
Lecture 2-1CS250: Intro to AI/Lisp Intelligent Agents Lecture 3-2 October 14 th, 1999 CS250.
ISBN Chapter 15 Functional Programming Languages.
CSE 341, S. Tanimoto Lisp Defining Functions with DEFUN Functions are the primary abstraction mechanism available in Lisp. (Others are structures.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
Functional Programming in Scheme and Lisp.
Lecture 6-2CS250: Intro to AI/Lisp Programming in Your Favorite Language Lecture 5-2 February 11 th, 1999 CS250.
Lisp Functional Language or Applicative Language –Achieves its effect by applying functions, either recursively or through composition Powerful, expressive,
LISP Data Types Functional Programming Academic Year Alessandro Cimatti
Introduction to LISP. Lisp Extensible: It lets you define new operators yourself Lisp programs are expressed as lisp data structures –You can write programs.
PRACTICAL COMMON LISP Peter Seibel 1.
11 Speed & Debug.  Lisp is really two languages:  A language for writing fast programs  A language for writing programs fast  In the early stage,
UMBC CMSC Common Lisp II. UMBC CMSC Input and Output Print is the most primitive output function > (print (list 'foo 'bar)) (FOO BAR) The.
PRACTICAL COMMON LISP Peter Seibel 1.
PRACTICAL COMMON LISP Peter Seibel 1.
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.
Lists CSC 358/ Outline Lab #1 / Homework #1 Lists A question List Internals of Lists List operations Extended Example.
Introduction to LISP Atoms, Lists Math. LISP n LISt Processing n Function model –Program = function definition –Give arguments –Returns values n Mathematical.
Chapter 5 Linked List by Before you learn Linked List 3 rd level of Data Structures Intermediate Level of Understanding for C++ Please.
1 FP Foundations, Scheme In Text: Chapter Chapter 14: FP Foundations, Scheme Mathematical Functions Def: A mathematical function is a mapping of.
1 Linked Lists Assignment What about assignment? –Suppose you have linked lists: List lst1, lst2; lst1.push_front( 35 ); lst1.push_front( 18 ); lst2.push_front(
PRACTICAL COMMON LISP Peter Seibel 1.
Artificial Intelligence and Lisp Lecture 6 LiU Course TDDC65 Autumn Semester,
Section 15.4, 15.6 plus other materials
Intelligent Agents Lecture 3-2 October 14th, 1999 CS250 Lecture 2-1
Edited by Original material by Eric Grimson
Example of formula (defun roots (a b c) (list
Lists in Lisp and Scheme
J.E. Spragg Mitthögskolan 1997
6.001 SICP Further Variations on a Scheme
John McCarthy Pioneer in AI Also Lisp Formalize common-sense reasoning
Announcements Quiz 5 HW6 due October 23
Defining Functions with DEFUN
Peter Seibel Practical Common Lisp Peter Seibel
Abstraction and Repetition
Common Lisp II.
Lisp.
LISP primitives on sequences
Lists in Lisp and Scheme
Presentation transcript:

PRACTICAL COMMON LISP Peter Seibel 1

CHAPTER 12 THEY CALLED IT LISP FOR A REASON: LIST PROCESSING 2

LIST Lists are instances of a primitive data type. Those simpler objects are pairs of values called cons cells, after the function CONS used to create them. CONS takes two arguments and returns a new cons cell containing the two values. These values can be references to any kind of object. Unless the second value is NIL or another cons cell, a cons is printed as the two values in parentheses separated by a dot, a so-called dotted pair. (cons 1 2) → (1. 2) The two values in a cons cell are called the CAR and the CDR after the names of the functions used to access them. (car (cons 1 2)) → 1 (cdr (cons 1 2)) → 2 3

LIST Both CAR and CDR are also SETFable places—given an existing cons cell, it’s possible to assign a new value to either of its values. (defparameter *cons* (cons 1 2)) *cons* → (1. 2) (setf (car *cons*) 10) → 10 *cons* → (10. 2) (setf (cdr *cons*) 20) → 20 *cons* → (10. 20) (defparameter *cons* (cons 1 ‘(2))) *cons* → (1 2) (setf (car *cons*) 10) → 10 *cons* → (10 2) (setf (cdr *cons*) 20) → 20 *cons* → (10 20) 4

LIST Lists are built by linking together cons cells in a chain. (singly linked list) The elements of the list are held in the CARs of the cons cells while the links to subsequent cons cells are held in the CDRs. The last cell in the chain has a CDR of NIL, which represents the empty list as well as the boolean value false. (cons 1 nil) → (1) (cons 1 (cons 2 nil)) → (1 2) (cons 1 (cons 2 (cons 3 nil))) → (1 2 3) Box-and-arrow diagrams The box on the left represents the CAR, and the box on the right is the CDR. For instance, the list (1 2 3) 5

LIST LIST function builds a cons cells and links them together. The following LIST expressions are equivalent to the previous CONS expressions: (list 1) → (1) (list 1 2) → (1 2) (list 1 2 3) → (1 2 3) Similarly, FIRST and REST are synonyms for CAR and CDR that we should use when we are dealing with cons cells as lists. (defparameter *list* (list )) (first *list*) → 1 (rest *list*) → (2 3 4) (first (rest *list*)) → 2 6

LIST A single list can hold objects of different types. (list "foo" (list 1 2) 10) → ("foo" (1 2) 10) The structure of the list 7

FUNCTIONAL PROGRAMMING AND LISTS Most of Common Lisp’s list-manipulation functions are written in a functional style. The reason is it allows them to return results that share cons cells with their arguments. For example, the function APPEND takes any number of list arguments and returns a new list containing the elements of all its arguments. (append (list 1 2) (list 3 4)) → ( ) 8

FUNCTIONAL PROGRAMMING AND LISTS Discussion: APPEND actually makes only two new cons cells to hold the values 1 and 2, linking them together and pointing the CDR of the second cons cell at the head of the last argument, the list (3 4). In general, APPEND must copy all but its last argument, but it can always return a result that shares structure with the last argument. (append (list 1 2) (list 3 4) (list 5 6)) → ( ) Other functions take similar advantage of lists’ ability to share structure. 9

“DESTRUCTIVE” OPERATIONS Because of Lisp’s functional heritage ( 繼承 ), operations that modify existing objects are called destructive( 破壞的 )—in functional programming, changing an object’s state “destroys” it since it no longer represents the same value. Two different kinds of destructive operations: For-side-effect operations Recycling operations 10

“DESTRUCTIVE” OPERATIONS For-side-effect operations are those used specifically for their side effects. For instance, consider these three definitions: (defparameter *list-1* (list 1 2)) (defparameter *list-2* (list 3 4)) (defparameter *list-3* (append *list-1* *list-2*)) *list-3* and *list-2* share structure just like the lists in the previous diagram. *list-1* → (1 2) *list-2* → (3 4) *list-3* → ( ) Now consider what happens when we modify *list-2*. (setf (first *list-2*) 0) → 0 *list-2* → (0 4) *list-3* → ( ) The change to *list-2* also changes *list-3* because of the shared structure: the first cons cell in *list-2* is also the third cons cell in *list-3*. 11

“DESTRUCTIVE” OPERATIONS Recycling operations are intended to be used in functional code. They use side effects only as an optimization. Unlike functions such as APPEND that reuse cons cells by including them, unmodified, in the list they return, recycling functions reuse cons cells as raw material, modifying the CAR and CDR as necessary to build the desired result. Thus, recycling functions can be used safely only when the original lists aren’t going to be needed after the call to the recycling function. For example: Let’s compare REVERSE, the nondestructive function that returns a reversed version of a sequence, to NREVERSE, a recycling version of the same function. 12

“DESTRUCTIVE” OPERATIONS REVERSE doesn’t modify its argument, it must allocate a new cons cell for each element in the list being reversed. (setf *list* (reverse *list*)) can be used to assign the result of REVERSE back to *list*. For example: Break 13 [17]> (defparameter *list* (list )) *LIST* Break 13 [17]> (reverse *list*) ( ) Break 13 [17]> *list* ( ) Break 13 [17]> (setf *list* (reverse *list*)) ( ) Break 13 [17]> *list* ( ) 13

“DESTRUCTIVE” OPERATIONS NREVERSE allows you to do exactly that. The N stands for non-consing, meaning it doesn’t need to allocate any new cons cells. Break 13 [17]> (defparameter *list* (list )) *LIST* Break 13 [17]> *list* ( ) Break 13 [17]> (nreverse *list*) ( ) Break 13 [17]> *list* ( ) 14

“DESTRUCTIVE” OPERATIONS Most recycling functions, like NREVERSE, have nondestructive counterparts that compute the same result. In general, the recycling functions have names that are the same as their nondestructive counterparts except with a leading N. However, not all do, including several of the more commonly used recycling functions such as NCONC, the recycling version of APPEND, and DELETE, DELETE-IF, DELETE-IF-NOT, and DELETE-DUPLICATES, the recycling versions of the REMOVE family of sequence functions. (defparameter *x* (list 1 2 3)) (append *x* (list 4 5 6)) → ( ) *x* → (1 2 3) (defparameter *x* (list 1 2 3)) (nconc *x* (list 4 5 6)) → ( ) *x* → ( ) 15

“DESTRUCTIVE” OPERATIONS NCONC builds its result in the following way: (defparameter *x* (list 1 2 3)) (nconc *x* (list 4 5 6)) → ( ) *x* → ( ) For each nonempty list it’s passed, NCONC sets the CDR of the list’s last cons cell to point to the first cons cell of the next nonempty list. It then returns the first list, which is now the head of the spliced-together result. 16

COMBINING RECYCLING WITH SHARED STRUCTURE To make matters worse, shared structure and recycling functions tend to work at cross purposes ( 目的相反 ). Nondestructive list functions return lists that share structure under the assumption that cons cells are never modified, but recycling functions work by violating that assumption. Sharing structure is based on the premise that we don’t care exactly what cons cells make up a list while using recycling functions requires that we know exactly what cons cells are referenced from where. In practice, the most common recycling idiom ( 習慣用法 ) is to build up a list to be returned from a function by “consing” onto the front of a list, usually by PUSHing elements onto a list stored in a local variable and then returning the result of NREVERSEing it. 17

COMBINING RECYCLING WITH SHARED STRUCTURE This is an efficient way to build a list because each PUSH has to create only one cons cell and modify a local variable and the NREVERSE just has to zip down the list reassigning the CDRs. Here’s a function that uses this idiom to build a list of the first n numbers, starting at zero: (defun upto (max) (let ((result nil)) (dotimes (i max) (push i result)) (nreverse result))) (upto 10) → ( ) 18

COMBINING RECYCLING WITH SHARED STRUCTURE The next most common recycling idiom is to immediately reassign the value returned by the recycling function back to the place containing the potentially recycled value. For instance, you’ll often see expressions like the following, using DELETE, the recycling version of REMOVE: (setf foo (delete nil foo)) This sets the value of foo to its old value except with all the NILs removed. Break 15 [19]> (defparameter foo (list 1 nil 2 nil 3)) FOO Break 15 [19]> foo (1 NIL 2 NIL 3) Break 15 [19]> (delete nil foo) ;(setf foo (delete nil foo)) (1 2 3) Break 15 [19]> foo (1 2 3) 19

COMBINING RECYCLING WITH SHARED STRUCTURE For example: > (defparameter *list-1* (list 1 2)) > (defparameter *list-2* (list 0 4)) > (defparameter *list-3* (append *list-1* *list-2*)) > *list-3* ( ) > (delete 4 *list-3*) (1 2 0) > *list-3* (1 2 0) > *list-2* (0) > (defparameter *list-2* (list 0 4)) > (defparameter *list-3* (append *list-1* *list-2*)) > (remove 4 *list-3*) (1 2 0) > *list-2* (0 4) 20

COMBINING RECYCLING WITH SHARED STRUCTURE Consider the above example: If we delete 4 from *list-3*: (setf *list-3* (delete 4 *list-3*)) → (1 2 0) DELETE will likely perform the necessary deletion by setting the CDR of the third cons cell to NIL, disconnecting the fourth cons cell, the one holding the 4, from the list. Because the third cons cell of *list-3* is also the first cons cell in *list-2*, the following modifies *list-2* as well: *list-2* → (0) If we use REMOVE instead of DELETE, it would’ve built a list containing the values 1, 2, and 0, creating new cons cells as necessary rather than modifying any of the cons cells in *list-3*. In that case, *list-2* wouldn’t have been affected. 21

COMBINING RECYCLING WITH SHARED STRUCTURE The sorting functions SORT, STABLE-SORT, and MERGE are also recycling functions when applied to lists. CL-USER> (defparameter *list* (list )) *LIST* CL-USER> (sort *list* #'<) ( ) ; looks good CL-USER> *list* (4) ; whoops! Break 15 [19]> (defparameter *list* (list )) *LIST* Break 15 [19]> (sort *list* #'<) ( ) Break 15 [19]> *list* ( ) The recycling functions should be rechecked in different compilers. 22

LIST-MANIPULATION FUNCTIONS The basic functions for getting at the elements of a list: FIRST and REST. Common Lisp also provides functions named for the other ordinals from SECOND to TENTH that return the appropriate element. The function NTH takes two arguments, an index and a list, and returns the nth (zero-based) element of the list. Similarly, NTHCDR takes an index and a list and returns the result of calling CDR n times. > (defparameter *list* (list )) > (nth 1 *list*)  2 > (nthcdr 1 *list*)  (2 3 4) > (nthcdr 0 *list*)  ( ) 23

LIST-MANIPULATION FUNCTIONS The 28 composite CAR/CDR functions are another family of functions we may see used from time to time. Each function is named by placing a sequence of up to four As and Ds between a C and R, with each A representing a call to CAR and each D a call to CDR. For examples: (caar list) ≡ (car (car list)) (cadr list) ≡ (car (cdr list)) (cadadr list) ≡ (car (cdr (car (cdr list)))) 24

LIST-MANIPULATION FUNCTIONS CAAR extracts the CAR of the CAR of the list it’s given; thus, the list it’s passed must contain another list as its first element. (caar (list 1 2 3)) → error (caar (list (list 1 2) 3)) → 1 (cadr (list (list 1 2) (list 3 4))) → (3 4) (caadr (list (list 1 2) (list 3 4))) → 3 In particular, they used to be used to extract the various parts of expressions passed to macros before the invention of destructuring parameter lists. For example: when (> x 10) (print x)) ;; the condition (cadr '(when (> x 10) (print x))) → (> X 10) ;; the body, as a list (cddr '(when (> x 10) (print x))) → ((PRINT X)) 25

LIST-MANIPULATION FUNCTIONS 26

LIST-MANIPULATION FUNCTIONS 27

MAPPING Another important aspect of the functional style is the use of higher-order functions, functions that take other functions as arguments or return functions as values. For examples: MAP, MAPCAR and MAPLIST (map 'vector #'* #( ) #( )) → #( ) (mapcar #'(lambda (x) (* 2 x)) (list 1 2 3)) → (2 4 6) (mapcar #'+ (list 1 2 3) (list )) → ( ) MAPCAR is the function most like MAP. Because it always returns a list, it doesn’t require the result-type argument MAP does. MAPLIST is just like MAPCAR except instead of passing the elements of the list to the function, it passes the actual cons cells. Break 16 [20]> (setf mon '( )) ( ) Break 16 [20]> (setf sums (maplist #'(lambda (x) (apply #'+ x)) mon)) ( ) 28

MAPPING Comparison: >(mapcar #'(lambda (x) (* 2 x)) (list 2 3 4)) (4 6 8) >(maplist #'(lambda (x) (apply #'* 2 x)) (list 2 3 4)) ( ) >(setf mon '( )) ( ) > (setf sums (maplist #'(lambda (x) (apply #'+ x)) mon)) ( ) > (setf sums (mapcar #'(lambda (x) (+ x)) mon)) ( ) 29