370 likes | 775 Views
Introductory Lisp Programming Lecture # 2. Main Topics Basic Lisp data types Lisp primitives Details of list handling Cons cells (boxes) & their representation in memory List operators: cons, append, rplaca, rplacd.. Lists as arguments to functions. Lisp Lecture #2. Exam #1
E N D
Introductory Lisp Programming Lecture # 2 • Main Topics • Basic Lisp data types • Lisp primitives • Details of list handling • Cons cells (boxes) & their representation in memory • List operators: cons, append, rplaca, rplacd.. • Lists as arguments to functions
Lisp Lecture #2 • Exam #1 • Will cover Lisp programming • February ???-th, take-home • Today: • Review lecture on Lisp • More on functions • More on Lisp internals • Non-destructive and destructive operations • Next time: • Problem solving using search (Chapter 3 R&N) • Read chapter before coming to class
Basic LISP Data Types Expression Sequence Atom Array Structure Thing id: 764 loc: (12 29).. 4, 7, 12.. Symbol Number List String ‘Rosebud (has arms 2) “Rosebud” Integer Ratio Float (12 7 32 78) (bob (has (arms 2) (legs 2))) 3 7/13 23.45
Logical Operators Truth values = T (true) and NIL (false) AND, OR, NOT, XOR.. Everything but NIL has a truth value of T - even 0!!! (and t t) => t; (and 1 0) => t ; (or nil nil 0) => t; (xor 1 t) => nil (not t) =>nil; (not nil) => t; (not 45) => nil; *Logical operators only evaluate as many arguments (left to right) as necessary to determine the truth value of the expression. (and nil (* 88 99 66)) => nil ;; the * is never evaluated (and (* 88 99) nil) => nil ;; the * IS evaluated due to L-R eval order (not (and (or nil nil) (xor 1 0))) => t ;; the xor is never evaluated * NIL is both false and the empty list, depending upon the context
a b a a a b b c c a b Dotted Pairs > (cons ‘a nil) => (a) > (cons ‘a (cons ‘b nil)) => (a b) > (cons ‘a ‘(b)) => (a b) > (cons ‘a ‘b) => (a . b) > (cons ‘(a b) ‘c) => ((a b) . c) > (cons (cons ‘a ‘b) ‘c) => ((a . b) . c) > (car ‘(a . b)) => a > (cdr ‘(a . b)) => b ; symbol > (cdr ‘(a b)) => (b) ; cons cell
Recursion • count-atoms • null • cond
Optional arguments Optional argument (root 4)==>2 (root 4 3)==>4 1/3 Binds to the cdr of list of arguments Binds to the car of list of arguments
More on Lisp Internals • Storage allocation • Non-destructive list operations • Destructive list operations • Pointer manipulation: setf, eq • Efficiency considerations
Internal List Representation • Free Storage List
equal • eq Two pointers point to the same location
Efficiency • user-reverse
Efficiency Considerations res is optional argument Argument list
Variable Assignment & Access Assignment SETF (setf y (+ 3 5)) => y assigned the value 8 (setf y ‘((a 1) (b 2) (c 3))) => y assigned to the data list * Can be used to set arbitrary locations in Lisp data structures (setf (second y) 88) => 88 y => ((a 1) 88 (c 3)) SETQ (setf x (+ 3 5)) => x assigned the value 8 * First argument must be a symbol, not a general location. Access Anytime a variable appears, it will be evaluated (i.e. its value will be accessed), unless the variable appears inside the scope of a single or double quote, or is an argument to a macro. > x => 8 > ‘x => x
Evaluating LISP Expressions (1) Evaluate := compute/fetch value of an expression Form := an expression to be evaluated A number evaluates to itself: > 76 => 76 A variable evaluates to its value: > (setf x 54) > x => 54 A quoted symbol evaluates to the symbol itself: > ‘z => z A string evaluates to itself: > “portland” => “portland”
Evaluating LISP Expressions (2) A single quoted list evaluates to a simple list of symbols > ‘(a b c) => (a b c) > ‘(+ 2 3) => (+ 2 3) An unquoted list evaluates to a function call > (+ 2 3) => 5 > (a b c) => ERROR: attempt to call an undeclared function ‘a Evaluate arguments left-to-right, then call function: > (setf bob 5 bill 7 sue 9) > (+ bob bill sue) => 21 ;; (Calls + with 3 values: 5, 7, 9) Polish notation: (operator operand1 operand2 … operandn) (+ 2 3 4 5) simpler than 2 + 3 + 4 + 5 + 6 if you can live with all the parentheses!! Parentheses => no need for arithmetic precedence rules > (+ (* a b) (* c d)) -vs- a*b + c*d
f1 8 f2 c f2 2 a f3 3 b Depth-First Evaluation Order • (f1 (f2 a (f3 b)) c 8 (f2 3 2))
List Accessors Data: y => ((a 1) (b 2) (c 3)) LENGTH (length ‘(a b c)) => 3; (length nil) => 0 FIRST (or CAR) (first ‘(a b c)) => a ; (first y) => (a 1) ; (first ‘y) => Error! REST (or CDR) (rest ‘(a b c)) => (b c); (rest y) => ((b 2) (c 3)); (first (rest y)) => (b 2); (first (first (rest y))) => b NTH (nth 0 ‘(a b c)) => a ; (nth 2 ‘(a b c)) => c NTHCDR (n nested calls to REST/CDR) (nthcdr 2 y) => ((c 3)) BUTLAST (everything but the last n elements) (butlast y 2) => ((a 1)) FIRST, SECOND, THIRD...TENTH return corresponding element of the list
List Constructors CONS (“construct”) (cons ‘a ‘(a b c)) => (a a b c); (cons ‘(a b) ‘(c d)) => ‘((a b) c d) (cons ‘a nil) => (a); (cons nil ‘(a b)) => (nil a b)) = (() a b) LIST (list ‘a ‘b) => (a b); (list ‘(a b) ‘c ‘d) => ((a b) c d) APPEND (append ‘(a b c) ‘(d e f)) => (a b c d e f); (append nil ‘(a b)) => (a b) These are not destructive: > (setf x ‘(a b c)) > (cons 62 x) => (62 a b c) > x => (a b c)
Destructive List Modifiers (1) PUSH/POP: treat list like a stack and alter symbol values (“destructive”) > (push 77 x) => (77 a b c) > x => (77 a b c) > (pop x) => 77 > x => (a b c) REVERSE (non-destructive) (reverse ‘(a b c)) => (c b a) ; (reverse ‘((a 1) (b 2))) => ((b 2) (a 1)) NREVERSE (destructive reverse => no copying, but use setf for safety) > (setf x '(a b c)) => (a b c) > (nreverse x) => (c b a) > x => (a) > (setf x '(a b c)) => (a b c) > (setf x (nreverse x)) => (c b a) > x => (c b a)
List Modifiers (2) SETF + List Accessors (Destructive!): > (setf y '(a b c)) => (a b c) > (setf (second y) 23) => 23 > y => (a 23 c) > (setf (second (cdr y)) 99) => 99 > y => (a 23 99) > (setf (cdr y) '(aaa bbb ccc)) => (aaa bbb ccc) > y => (a aaa bbb ccc)
2 3 1 y trondheim ntnu idi lade > (setf x ‘(ntnu idi lade)) => (ntnu idi lade) > (setf y (cons ‘trondheim x)) => (trondheim ntnu idi lade) > (setf z (cons ‘(1 2 3) y)) => ( (1 2 3) trondheim ntnu idi lade) Cons Cells z Shared area x = cons cell (standard lisp terminology) or box (Winston) *Each call to cons uses one new cons cell and sets car to first elem, cdr to 2nd.
1 2 3 List Creation > (setf x ‘(a b c)) ;; Uses 3 newcons cells ; same as (setf x (list ‘a ‘b ‘c)) > (setf y ‘(1 2 3)) ;; Uses 3 more new cons cells; same as (setf y (list 1 2 3)) > (setf z (list x y ‘the ‘end)) ;; Uses 4 more new cons cells z end the y x a b c
1-byte data type 4-byte pointer to cell’s value 4-byte pointer to next cons cell Memory (setf x ‘(ntnu idi lade 639)) Cons cells in memory Symbol Table FFE073: AAA050: ntnu value: unbound AAA050 FFF101 idi value: unbound AAA150: FFF101: AAA150 AAA250: lade value: unbound FFF252 x value: FFE073 FFF252: AAA250 Simple Data Storage *Cons cells, symbol table and regular data storage are all in memory FFF849 CCC250: 639 FFF849: *Each symbol has many possible properties in the symbol table CCC250 000000
Non-Destructive List Operations Many beginners do this mistake They think about variables as separate “containers”
APPEND > (setf x ‘(ntnu idi lade)) > (setf y ‘(1 2 3)) > (setf z (append x y)) > z (ntnu idi lade 1 2 3) > x (ntnu idi lade) x ntnu idi lade z *Copies all of x’s cons cells, so x is unchanged. y copied 1 2 3 shared
More on Destructive List Operations NCONC is destructive operation!!!!!!
Destructive Lisp Operations SETF is destructive operation!!!!!!
y ‘Destructive’ function => some of the original arguments may be changed 1 2 3 NCONC (Destructive Append) (nconc list1 list2…listn) - changes ‘next ptr in the last cons cells of list1 - listn-1 (setf x ‘(ntnu idi lade) y ‘(1 2 3)) (setf z (nconc x y)) > z (ntnu idi lade 1 2 3) > x (ntnu idi lade 1 2 3) z x NCONC is destructive APPEND !!!!! ntnu idi lade
RPLACA = (SETF (FIRST ..)) SETF can make destructive modifications to lists. > (setf x ‘(a b c)) > (setf y x) > (setf (first y) 99) > y (99 b c) > x (99 b c) > (setf (nth 2 y) 88) > x (99 b 88) > (rplaca y 55) > x (55 b 88) y x b 99 88 c a 55 RPLACA is destructive !!!!!
RPLACD = (SETF (REST ..)) y RPLACD is destructive !!!!! x > (setf x ‘(a b c)) > (setf y x) > (setf (rest y) ‘(22 33)) > x (a 22 33) > (rplacd y ‘(77 88)) > x (a 77 88) b c a 22 33 *There are no remaining pointers to (b c) nor (22 33). Their cons cells should be freed up for cons and list to reuse. This is, they should be garbage collected. LISP has automatic garbage collection. 77 88
(defun change1 (list) (setf (first list) (first (last list)))) (defun change2 (list) (cons (first (last list)) (rest list))) x value: a b c change1 list: change2 list: List Parameters in Function Calls (1) • LISP uses “call by value” for all parameters. • In the case of lists, this means that the formal parameters get a copy of the pointer to the list,not a copy of the whole list. > (setf x ‘(a b c))
(defun change1 (list) (setf (first list) (first (last list)))) (defun change2 (list) (cons (first (last list)) (rest list))) change1 list: List Parameters in Function Calls (2) SETF is destructive !!!!! > (setf x ‘(a b c)) > (change1 x) * Change1 uses setf(first..), which is destructive. So x changes also. x value: a b c c
(defun change1 (list) (setf (first list) (first (last list)))) (defun change2 (list) (cons (first (last list)) (rest list))) change2 list: List Parameters in Function Calls (3) CONS is not destructive !!!!! > (setf x ‘(a b c)) > (change2 x) * Change2 uses cons, which is non-destructive. So x is unchanged. x value: a b c c