1 / 36

Processing Symbolic Data

Processing Symbolic Data. More Standard Functions. Some more useful functions and predicates (symbolp s ) T for atomic symbol s s (numberp s ) T for numbers s (consp s ) T for cons value s ( i.e . it has car a nd cdr) (listp s ) T for list s ( maybe empty ) Selectors/accessors

shawn
Download Presentation

Processing Symbolic Data

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Processing Symbolic Data

  2. More Standard Functions • Some more useful functions and predicates • (symbolps)Tfor atomic symbolss • (numberps)T fornumbers s • (consps)T for cons values(i.e. it has car and cdr) • (listps)T forlists(maybe empty) • Selectors/accessors • cxx...xr selectors - combinationsof car/cdr • (caar x) = (car (car x)) (cadr x) = (car (cdr x))... • Similarly caaar, caadr, ..., cdddr, caaaar, caaadr, ..., cddddr • (length s) how many elements in s • (nth ns) n-thelement of list s (leftmost is 0th!) • (nthcdr ns)n-th cdr • (last s)last cons cell • (butlast s)list s without the last element • (butlast sn)n elements from the end removed

  3. All those are standard, but could be defined as follows • (defun nth (N S) ; N-thelement of list S • (cond ((= N 0) (car S)) ;car is 0th! • (T (nth (1- N) (cdr S))) • ) ) • (defun nthcdr (N S) ; n-th cdr • (cond ((= N 0) S) • (T (nthcdr (1- N) (cdr S))) • ) ) • (defun last (S) ; the last cons cell • (cond ((null S) NIL) • ((null (cdr S) S) • (T (last (cdr S))) • ) ) • (defun butlast (S) ; list S without the last element • (cond ((or (null S) (null (cdr S)) NIL) • (T (cons (car S) • (butlast (cdr S)) • ) ) ) )

  4. Still More Functions ... • (member Elm Lst) looks for Elm in Lst, returns the part starting • with Elm • (remove Elm Lst) deletes Elm from Lst (returns a copy) • (subst New Old Lst) substitutes New for Old in Lst • (returns a copy) • (nsubst New Old Lst)substitutes New for Old in Lst • (returns a modified Lst) • (reverse Lst) reverses Lst (returns a fresh list)

  5. (defun member (Elm Lst) • (cond ((null Lst) NIL) • ((eql Elm (car Lst)) Lst) ; eq, eql, equal ... • (T (member Elm (cdr Lst))) • ) ) • (defun remove (Elm Lst) • (cond ((null Lst) NIL) • ((eql Elm (car Lst)) ; Elm found? • (remove Elm (cdr Lst))) ; remove from rest • (T (cons (car Lst) ; else copy car • (remove Elm (cdr Lst))) • ) ) • (defun subst (New Old Lst) • (cond ((null Lst) NIL) • ((eql Old (car Lst)) • (cons New • (subst New Old (cdr Lst)))) • (T (cons (car Lst) • (subst New Old (cdr Lst)))) • ) ) ; what about substitution in all levels ???

  6. (defun nsubst (New Old Lst) • (cond ((null Lst) NIL) • ((eql Old (car Lst)) • (setf (car Lst) New) • (setf (cdr Lst) (nsubst New Old (cdr Lst))) • Lst) • (T (setf (cdr Lst) (nsubst New Old (cdr Lst))) • Lst) • ) ) ; calls for some improvement ... • ; How shall we reverse a list ??? • (defun reverse (Lst) • (if (null Lst) NIL • (append (reverse (cdr Lst)) • (list (car Lst))) • ) ) • (defun append (X Y) • (if (null X) Y • (cons (car X) • (append (cdr X) Y)) • ) )

  7. ; Can we do reverse any better ??? • (defun reverse (Lst) • (rev-iter Lst Nil)) • (defun rev-iter (Lst Acc) • (if (null Lst) Acc • (rev-iter (cdr Lst) (cons (car Lst) Acc)) • ) )

  8. CL-USER 1 > (rev S) • 0 REV > ... • >> LST : (A B C) • 1 REV-ITER > ... • >> LST : (A B C)>> ACC : NIL • 2 REV-ITER > ... • >> LST : (B C)>> ACC : (A) • 3 REV-ITER > ... • >> LST : (C) >> ACC : (B A) • 4 REV-ITER > ... • >> LST : NIL>> ACC : (C B A) • 4 REV-ITER < ... • << VALUE-0 : (C B A) • 3 REV-ITER < ... • << VALUE-0 : (C B A) • 2 REV-ITER < ... • << VALUE-0 : (C B A) • 1 REV-ITER < ... • << VALUE-0 : (C B A) • 0 REV < ... • << VALUE-0 : (C B A) • (C B A)

  9. In a simplified presentation: • (rev (A B C)) • (rev-iter (A B C) () ) • (rev-iter (B C) (A) ) • (rev-iter (C) (B A) ) • (rev-iter () (C B A) )  (C B A) • returned (C B A) • returned (C B A) • returned (C B A) • returned (C B A) • returned (C B A)

  10. eval, apply and funcall • > (defvar S '(+ 1 2)) • > S • (+ 1 2) • > (eval S) • 3 • > S • (+ 1 2) • As a result: any (properly constructed) expression created during program execution can be evaluated again • (eval Form ) • (fn arg1 ... agrn)(apply Fn ArgList ) • (funcall Fn Arg1 ... Argn )

  11. eval, apply and funcall • Remind the summation procedure • (defun sum (S) • (if (null S) 0 • (+ (car S) (sum (cdr S))) • ) ) • (defun app-sum (S) (apply #'+ S)) • What if we want to sum-up results of some function • S = (a1 a2 a3 ... an) sum-f = ff(a1) + ff(a2) + ... + ff(an) • (defun sum-f (FF S) • (if (null S) 0 • (+ (FF (car S)) • (sum-f FF (cdr S))) • ) )

  12. eval, apply and funcall • Remind the summation procedure • (defun sum (S) • (if (null S) 0 • (+ (car S) (sum (cdr S))) • ) ) • (defun app-sum (S) (apply #'+ S)) • What if we want to sum-up results of some function • S = (a1 a2 a3 ... an) sum-f = ff(a1) + ff(a2) + ... + ff(an) • (defun sum-f (FF S) • (if (null S) 0 • (+ (funcall FF (car S)) ; !!! IMPORTANT !!! • (sum-f FF (cdr S))) • ) )

  13. R e c u r s i o n • Lisp = Recursion • Taxonomy of recursion • nested recursion • (defun Ack (m n); (Ack 4 5) stack overflow • (cond ((zerop m) (1+ n)) • ((zerop n) (Ack (1- m) 1)) • (T (Ack (1- m) (Ack m (1- n)))))) • tree recursion • (defun Fib (n); (Fib 35) took 26.328 s • (if (< n 2)n • (+ (Fib (- n 1))(Fib (- n 2))) • )) nested recursive call two recursive calls

  14. linear recursion • (defun linLen (s) • (if (null s) 0 • (1+ (linLen (cdr s))) • ) ) • tail recursion • (defun trLen (s) (tailLen s 0)) • (defun tailLen (s acc) • (if (null s) acc • (tailLen (cdr s) (1+ acc)) • ) ) • Tail recursion is the most efficient and can be transformed into explicit iteration mechanically. just one recursive call one recursive call, no pending operations

  15. General rule of recursive design • first test for trivial cases (such as 0, 1, NIL, atom, ... ) • then develop branches with recursive calls in which the procedure is applied to reduced arguments (1- N), (cdr S), ... • Example - copyinga list (highest level only) • (defun Copy (S) • (if (null S) NIL • (cons (car S) (Copy (cdr S))) )) • Now copying at all levels • (defun CopyAll (S) • (cond ((null S) nil) • ((atom S) S) • ((cons (CopyAll (car S)) • (CopyAll (cdr S)))) ))

  16. Sorting Recursively • Insertion Sortalgorithm • (defun Isort (S) (sort-iterSNIL)) • (defun sort-iter (SSeq) ; Seq is already sorted part • (if (null S) Seq; sorting finished • (sort-iter (cdr S); sort the rest • (Insert (car S) Seq))) • ) ) • (defun Insert (XSeq) ;insert Xinto Seq • (cond ((null Seq) (list X)) • ((< X (car Seq)) (cons XSeq)) • (T (cons (car Seq)(Insert X (cdr Seq)))) • ) ) • (defun Isort (S) (sort-iterS));second arg missing • (defun sort-iter (S&optional Seq) ;Seq is optional • ...

  17. Sorting Iteratively • Insertion Sortalgorithm • (defun Isort (S) (sort-iter(cdr S)(list (car S)))) • (defun sort-iter (SSeq) ; Seq is already sorted part • (dolist (E SSeq) ; going through list S • (setf Seq (Insert ESeq)); insert E into Seq • ) ) • (defun Insert (XSeq) ;insert Xinto Seq <> nil !!! • (do ((SSeq (cdr S)) (P nil S)(LX (list X))) • ((or (null S) (< X (car S)) • (setf (cdr LX) S) • (if (null P) • (setf Seq LX) • (setf (cdr P) LX)) • Seq • ) ) P S 1 2 4 5 Seq 3 LX

  18. Sets as Lists • set = list of atoms, no repetition • typical set operations - union, intersection, difference, ... • (defun Union (A B) ; A  B • (cond ((null A) B) • ((member (car A) B) (Union (cdr A) B)) • (T (cons (car A) (Union (cdr A) B))) )) • (defun Intersection (A B) ; A  B • (cond ((null A) NIL) • ((member (car A) B) • (cons (car A) (Intersection (cdr A) B))) • (T (Intersection (cdr A) B)) )) • (defun Difference (A B) ; A - B • (cond ((null A) NIL) • ((member (car A) B) (Difference (cdr A) B)) • (T (cons (car A) (Difference (cdr A) B))) ))

  19. Recursively Searching Subsequences • Given sequences p = (p1 p2 ... pn) and q = (q1 q2 ... qm)find the first occurrence of p in q (if any). • p =(A B B A) q =(A B C A B B A C A) → (A B B A C A) q =( A BC A B B A C A ) p =( A BB A ) we test whether p is a prefix of q, if not advance to the next position in q q =( A B C A B B A C A ) p =( A B B A ) q =( A B C A B B A C A ) p =( A B B A ) q =( A B C A B B A C A ) p =( A B B A )

  20. (defun sub-seq1 (p q) • (cond ((test-prefix p q) q); if p is prefix of q • ((null q) NIL) ; p was not found • (T (sub-seq1 p (cdr q))) ; move to the right • ) ) • (defun sub-seq2 (p q) ; first compare list lengths • (cond ((> (length p) (length q)) NIL) • ((test-prefix p q) q ; if p is prefix of q • (T (sub-seq2 p (cdr q))) ; step to the right • ) ) • ? Which version is faster and why ? • (defun test-prefix (pq) • (cond ((null p)) • ((null q) NIL) • ((eq (car p) (car q)) • (test-prefix (cdr p) (cdr q))) • ) ) • (defun test-prefix (&key (:prefix p)(:sequence q)) • ... (test-prefix :sequence (cdr q) :prefix (cdr p)))

  21. Tricks withArguments • Variable number of aguments ... &rest: • (defun min-max1 (S) ; S is a list of numbers • (list (apply #'min S) (apply #'max S))) • (defun min-max2 (&rest S) ; numbers only • (list (apply #'min S) (apply #'max S))) • (min-max1 '(4 2 6 3 7 1)) • (min-max2 4 2 6 3 7 1) • Keywords we have already seen • &optionalx(xdefault )(xdefault flag ) • &keyx(xdefault )(xdefault flag ) key is :x • ((:yx)default )((:yx)default flag )

  22. Multiple Values • Lisp functions can return ANY number of values (not just one) • > (values 1 2 3) ; or (value-list '(1 2 3)) • 1 • 2 • 3 • (multiple-value-setq VarList ValueForm ) > (multiple-value-setq (a b c) (values 1 2 3)) ; a=1, b=2, c=3 • (multiple-value-bind VarList ValueForm Form1 ... ) > (multiple-value-bind (a b c) (values 1 2 3) (list c b a))  (3 2 1)

  23. Multiple Values • (multiple-value-call Fn Form1 Form2 ... ) • (multiple-value-call #'list 1 (values 2 3 4) 5) •  (1 2 3 4 5) • (multiple-value-list Form ) • (multiple-value-list (values 1 2 3))  (1 2 3) • (multiple-value-prog1 Form1 Form2 ... ) • (multiple-value-prog1 (values 1 2 3) (cons a b)) • 1 • 2 • 3

  24. Programming Example(adopted from http://fare.tunes.org/cgi-bin/viewcvs.cgi/fare/lisp/fibonacci.lisp) • Back to Fibonacci – how to improve efficiency: • (defun AFib (n) (FibTail n 0 1)) • (defun FibTail (n a b) • (if (zerop n) a) • (FibTail (1- n) b (+ a b)) ) ) • (AFib 50) ; stack overflow ... • (defun BFib (n) ; iterative-only design ... • (loop repeat n • with p = 0 with q = 1 • do (psetq p q • q (+ p q)) • finally (return p))) • (FastFib 100000) ; calculated in 2.75 s • Good enough? Not?? Right!

  25. Programming Example (cont. 1) • Consider the following simple design pattern for iteration: • (defun iter-1 (f n &rest args) • (if (zerop n) (apply #'values args) • (apply #'iter-1 f (- n 1) • (multiple-value-list (apply f args))))) • (defun Fib-step (a b) (values b (+ a b))) • (iter-1 'Fib-step 190 0 1) ; stack overflow ... • Iteration can be accelerated using function composition • (defun compose/2 (f g) • (lambda (&rest args) • (apply f (multiple-value-list (apply g args))))) • (defun compose (&rest functions) • (if (null functions) #'values • (compose/2 (car functions) • (apply 'compose (cdr functions)))))

  26. Programming Example (cont. 2) • (defun iter-2 (f n &rest args) • (apply (apply #'iter-1 f (- n 1) • (multiple-value-list (apply f args))))) • (defun Fib-step (a b) (values b (+ a b))) • (iter-2 'Fib-step 190 0 1) ; stack overflow ... • Iteration can be accelerated using function composition • (defun compose/2 (f g) • (lambda (&rest args) • (apply f (multiple-value-list (apply g args))))) • (defun compose (&rest functions) • (if (null functions) #'values • (compose/2 (car functions) • (apply 'compose (cdr functions))))) • (defun iter-2 (f n &rest args) • (apply (apply 'compose (loop for i below n collect f)) • args)) • (iter-2 'Fib-step 103 0 1) ; stack overflow ...

  27. Programming Example (cont. 3) • Remember tricky exponentiation: • (defun nat-expt (base exponent &optional (factor 1)) • (if (zerop exponent) factor • (nat-expt (* base base) • (ash exponent -1) • (if (oddp exponent) (* base factor) factor)))) • (defun fn-expt (fn iterations &optional (seed #'values)) • (if (zerop iterations) seed • (fn-expt (compose/2 fn fn) • (ash iterations -1) • (if (oddp iterations) (compose fn seed) seed) • ) ) ) • (defun iter-3 (f n &rest args) • (apply (fun-expt f n) args)) • (iter-3 'fib-step 100000 0 1) ; calculated in 3.5 s ???

  28. Programming Example (cont. 4) • (defun generic-expt (composer function iterations seed) • (if (zerop iterations) seed • (generic-expt composer • (funcall composer function function) • (ash iterations -1) • (if (oddp iterations) • (funcall composer function seed) • seed)))) • (defun matrix-expt (m n &optional • (seed (identity-matrix (matrix-columns m)))) • (generic-expt 'matrix-compose m n seed)) • (defun fast-fib (n) • (matrix-element (matrix-expt '((0 1) (1 1)) n) 0 1)) • (fast-fib 100000) ; calculated in 0.343 s • (very-fast-fib 100000) ; calculated in 0.156 s

  29. Programming Example (cont. 5) • (defun very-fast-fib (n) • (declare (optimize (speed 3) (safety 0) (debug 0))) • (check-type n fixnum) • (let ((a 0) (b 1) ;;; the matrix to exponentiate • (p 0) (q 1)) ;;; the seed vector to which to apply it • (loop • for c = (+ a b) • until (zerop n) • when (oddp n) • do (psetq p (+ (* a p) (* b q)) • q (+ (* b p) (* c q))) ;;; apply current mtrx • do (psetq n (ash n -1) ;;; halving the exponent • a (+ (* a a) (* b b)) • b (* b (+ a c))) ;;; squaring current matrix • finally (return p))))

  30. Local vs. Global Variables ... • A simplified definition: • extent– the interval of time during which a reference to a variable is defined (can be dynamic or indefinite) • scope– the textual region of code in which reference to a variablecan occur (can be lexical or indefinite) • (defvar X) ; creates a dynamic (global) variable X • (defun FF (X) ...) ; creates a local variable X • Lisp uses lexical scoping as a rule, exceptions need an explicit specialdeclaration (defvar makes specialvars).

  31. Local vs. Global Variables ...

  32. Example – A Simple Counter ... • (defvar *counter* 0) ; a global (dynamic) variable • (defun increment-c () (incf *counter* )) ; ??? • (defun reset-c () (setf *counter* 0)) • (defun counter-value () *counter*) • (let ((counter 0)) ; local counter introduced • (defun incr-let () (incf counter )) • (defun reset-let () (setf counter 0)) • (defun c-val-let () counter) • ) closure

  33. Local vs. Global Variables ... • General form of let: • (let ((var-1 init-1)(var-2 init-2) ... (var-n init-n)) • exp-1 ... exp-k) • if no initial value specified,NIL is used, expk is the resulting value. • (let* ...)is similar to let, but initializations are performed in sequence • Modification of (variable) values: • (setfplace-1 new-value-1 • place-2 new-value-2 • ... • place-N new-value-N)

  34. Generalized Variables • What are the places to be setf-ed ?? • (defvar X '(1 2 3 4 5 6)) ; X • (car X) ; 1 • (setf (car X) 0) ; 0 • X ; (0 2 3 4 5 6) • (nth 3 X) ; 4 • (setf (nth 3 X) 14) ; 14 • X ; (0 2 3 14 5 6) • (cdr X) ; (2 3 14 5 6) • (setf (cdr X) '(YA BASTA)) ; (YA BASTA) • X ; (0 YA BASTA) • Possibilities for place specification (generalized variables) • nth, first, second, ..., tenth, car, cdr, caar, ..., cddddr, • get, getf • and some more ...

  35. Value-Changing Functions • Original modifiers • (rplaca x y ) (rplacd x y ) • (defvar X '(A B)) ; X • (defvar Y '(C)) ; Y • X ; (A B) • (rplaca X Y) ; ((C) B) • (setf X '(A B)) ; (A B) • (rplacd X Y) ; (A C) • (rplaca X X) ; ??? • (rplacd Y Y) ; ??? • More modifiers • (incf x [incr] ) (decf x [decr] )

  36. Defining "setf" functions • We can extend functions that create generalized variables. Assume we want last to be used in setf with the effect of changing the last list element. • (defun (setf last( (val lst) • (setf (car (last lst)) val) • ) • > (defvar X '(A B)) • (A B) • > (setf (last X) 'C) • (A C) • General format • (defun (setf fun) (newval arg1 arg2 ...) body) • (setf (fun arg1 arg2 ...) val)

More Related