Presentation is loading. Please wait.

Presentation is loading. Please wait.

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.

Similar presentations


Presentation on theme: "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."— Presentation transcript:

1 1 Lists in Lisp and Scheme

2 2 Lists are Lisp’s fundamental data structures. Lists are Lisp’s fundamental data structures. However, it is not the only data structure. However, it is not the only data structure. There are arrays, characters, strings, etc. There are arrays, characters, strings, etc. Common Lisp has moved on from being merely a LISt Processor. Common Lisp has moved on from being merely a LISt Processor. However, to understand Lisp and Scheme you must understand lists However, to understand Lisp and Scheme you must understand lists common functions on them common functions on them how to build other useful data structures using them. how to build other useful data structures using them.

3 3 In the beginning was the cons (or pair) What cons really does is combines two objects into a two-part object called a cons in Lisp and a pair in Scheme What cons really does is combines two objects into a two-part object called a cons in Lisp and a pair in Scheme Conceptually, a cons is a pair of pointers -- the first is the car, and the second is the cdr. Conceptually, a cons is a pair of pointers -- the first is the car, and the second is the cdr. Conses provide a convenient representation for pairs of any type. Conses provide a convenient representation for pairs of any type. The two halves of a cons can point to any kind of object, including conses. The two halves of a cons can point to any kind of object, including conses. This is the mechanism for building lists. This is the mechanism for building lists. (pair? ‘(1 2) ) => T (pair? ‘(1 2) ) => T nil a

4 4 Pairs Lists in CL and Scheme are defined as pairs. Lists in CL and Scheme are defined as pairs. Any non empty list can be considered as a pair of the first element and the rest of the list. Any non empty list can be considered as a pair of the first element and the rest of the list. We use one half of the cons to point to the first element of the list, and the other to point to the rest of the list (which is either another cons or nil). We use one half of the cons to point to the first element of the list, and the other to point to the rest of the list (which is either another cons or nil). nil a

5 5 Box notation nil a A one element list (A) nil ab c A list of 3 elements (A B C) Where NIL = ‘( )

6 6 What sort of list is this? nil a d b c > (set! z (list ‘a (list ‘b ‘c) ‘d)) (A (B C) D)  (car (cdr z))  ?? Z

7 7 Pair? The function pair? returns true if its argument is a cons (pair? = consp in CL) The function pair? returns true if its argument is a cons (pair? = consp in CL) So list? could be defined: So list? could be defined: (defun myListp (x) (or (null x) (consp x))) (defun myListp (x) (or (null x) (consp x))) Since everything that is not a pair is an atom, the predicate atom could be defined: Since everything that is not a pair is an atom, the predicate atom could be defined: (defun myAtom (x) (not (pair? x))) (defun myAtom (x) (not (pair? x))) Remember, nil is both an atom and a list. Remember, nil is both an atom and a list.

8 8 Equality Each time you call cons, Scheme allocates a new piece of memory with room for 2 pointers. Each time you call cons, Scheme allocates a new piece of memory with room for 2 pointers. So if we call cons twice with the same arguments, we get back two values that look the same, but are in fact distinct objects: So if we call cons twice with the same arguments, we get back two values that look the same, but are in fact distinct objects: > (define l1 (cons 'a ‘())) (A)  (define l2 (cons 'a nil)))  (A)  (eq? l1 l2)  #f  (equal l1 l2)  #t  (and (eq? (car l1)(car l2)) (eq? (cdr l1)(cdr l2)))  #t

9 9 Equal? We also need to be able to ask whether two lists have the same elements. We also need to be able to ask whether two lists have the same elements. CL provides an equality predicate for this, equal. CL provides an equality predicate for this, equal. Eq? returns true only if its arguments are the same object, and Eq? returns true only if its arguments are the same object, and equal, more or less, returns true if its arguments would print the same. equal, more or less, returns true if its arguments would print the same. > (equal? l1 l2) T Note: if x and y are eq?, they are also equal?

10 10 Equal? (define (equal? x y) ; this is ~ how equal? could be defined ; this is ~ how equal? could be defined (cond ((number? x) (= x y)) (cond ((number? x) (= x y)) ((not (pair? x)) (eq? x y)) ((not (pair? x)) (eq? x y)) ((not (pair? y)) nil) ((not (pair? y)) nil) ((equal (car x) (car y)) ((equal (car x) (car y)) (equal (cdr x) (cdr y))))) (equal (cdr x) (cdr y)))))

11 11 Does Lisp have pointers? One of the secrets to understanding Lisp is to realize that variables have values in the same way that lists have elements. One of the secrets to understanding Lisp is to realize that variables have values in the same way that lists have elements. As conses have pointers to their elements, variables have pointers to their values. As conses have pointers to their elements, variables have pointers to their values. What happens, for example, when we set two variables to the same list: What happens, for example, when we set two variables to the same list: > (set! x ‘(a b c)) (A B C) > (set! y x) (A B C) This is just like in Java This is just like in Java

12 12 The location in memory associated with the variable x does not contain the list itself, but a pointer to it. The location in memory associated with the variable x does not contain the list itself, but a pointer to it. When we assign the same value to y, Sccheme copies the pointer, not the list. When we assign the same value to y, Sccheme copies the pointer, not the list. Therefore, what would the value of Therefore, what would the value of > (eq? x y) be, #t or #f? Does Scheme have pointers?

13 13 Building Lists The function copy-list takes a list and returns a copy of it. The function copy-list takes a list and returns a copy of it. The new list will have the same elements, but contained in new conses. The new list will have the same elements, but contained in new conses. > (set! x ‘(a b c)) (A B C) > (set! y (copy-list x)) (A B C) Spend a few minutes to draw a box diagram of x and y to show where the pointers point. Spend a few minutes to draw a box diagram of x and y to show where the pointers point.

14 14 LISP’s Copy-list Copy-list is a built in function but could be defined as follows (define (copy-list s) (if (not (pair? s)) (if (not (pair? s)) s (cons (copy-list (car s)) (cons (copy-list (car s)) (copy-list (cdr s))))) (copy-list (cdr s))))) There is also a copy-tree that makes a copy of the entire s-expression.

15 15 Append TheScheme/Lisp function append returns the concatenation of any number of lists: TheScheme/Lisp function append returns the concatenation of any number of lists: > (append ‘(a b) ‘(c d) ‘(e)) (A B C D E) Append copies all the arguments except the last. Append copies all the arguments except the last. If it didn’t copy all but the last argument, then it would have to modify the lists passed as arguments. Such side effects are very undesirable, especially in functional languages. If it didn’t copy all but the last argument, then it would have to modify the lists passed as arguments. Such side effects are very undesirable, especially in functional languages.

16 16 append The two argument version of append could have been defined like this. The two argument version of append could have been defined like this. (define (append2 s1 s2) (if (null? s1) s2 (cons (car s1) (append2 (cdr s1) s2)))) (append2 (cdr s1) s2)))) Notice how it ends up copying the top level list structure of it’s first argument. Notice how it ends up copying the top level list structure of it’s first argument.

17 17 List access functions To find the element at a given position in a list use the function list-ref (nth in CL). To find the element at a given position in a list use the function list-ref (nth in CL). > (list-ref ‘(a b c) 0) A and to find the nth cdr, use list-tail (nthcdr in CL). and to find the nth cdr, use list-tail (nthcdr in CL). > (list-tail ‘(a b c) 2) (C) Both functions are zero indexed. Both functions are zero indexed.

18 18 Lisp’s nth and nthcdr (define (nth (n l) (cond ((null? l) nil) (cond ((null? l) nil) ((= n 0) (car l)) ((= n 0) (car l)) (#t (nth (- n 1) (cdr l))))) (#t (nth (- n 1) (cdr l))))) (define (nthcdr n l) (cond ((null? l) nil) (cond ((null? l) nil) ((= n 0) (cdr l)) ((= n 0) (cdr l)) (#t (nthcdr (- n 1) (cdr l))))) (#t (nthcdr (- n 1) (cdr l)))))

19 19 Accessing lists The function last returns the last element in a list The function last returns the last element in a list  (define (last l) (if (null? (cdr l)) (if (null? (cdr l)) (car l) (car l) (last (cdr l)))) (last (cdr l)))) > (last ‘(a b c)) (C) Note: in CL, last returns the last cons cell Note: in CL, last returns the last cons cell We also have: first, second, third, and CxR, where x is a string of up to four as or ds. We also have: first, second, third, and CxR, where x is a string of up to four as or ds. E.g., cadr, caddr, cddr, cdadr, … E.g., cadr, caddr, cddr, cdadr, …

20 20 Member Member returns true, but instead of simply returning t, its returns the part of the list beginning with the object it was looking for. Member returns true, but instead of simply returning t, its returns the part of the list beginning with the object it was looking for. > (member ‘b ‘(a b c)) (B C) member compares objects using equal? member compares objects using equal? There are versions that use eq? and eqv? And that take an arbitrary function There are versions that use eq? and eqv? And that take an arbitrary function

21 21 Memf If we want to find an element satisfying an arbitrary predicate we use the function memf: If we want to find an element satisfying an arbitrary predicate we use the function memf: > (memf odd? ‘(2 3 4)) (3 4) Which could be defined like: (define (memf f l) (cond ((null? l) #f) (cond ((null? l) #f) ((f (car l)) l) ((f (car l)) l) (#t (memf f (cdr l))))) (#t (memf f (cdr l)))))

22 22 Dotted Lists The kind of lists that can be built by calling list are more precisely known as proper lists. The kind of lists that can be built by calling list are more precisely known as proper lists. A proper list is either the empty list, or a cons whose cdr is a proper list. However, conses are not just for building lists -- whenever you need a structure with two fields you can use a cons. However, conses are not just for building lists -- whenever you need a structure with two fields you can use a cons. You will be able to use car to refer to the first field and cdr to refer to the second. You will be able to use car to refer to the first field and cdr to refer to the second. > (set! pair (cons ‘a ‘b)) (A. B) Because this cons is not a proper list, it is displayed in dot notation. Because this cons is not a proper list, it is displayed in dot notation. In dot notation the car and cdr of each cons are shown separated by a period.

23 23 A pair that isn’t a proper list is called a dotted pair. A pair that isn’t a proper list is called a dotted pair. However, remember that a dotted pair isn’t really a list at all. However, remember that a dotted pair isn’t really a list at all. It is a just a two part data structure. It is a just a two part data structure. ab (A. B)

24 24


Download ppt "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."

Similar presentations


Ads by Google