functional programming
DESCRIPTION
Functional Programming. 04 Control. Control-Blocks. Common Lisp has 3 basic operators for creating blocks of code progn block tagbody If ordinary function calls are the leaves of a Lisp program, these operators are used to build the branches. Control-Blocks. - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/1.jpg)
Functional Programming04 Control
![Page 2: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/2.jpg)
Control-BlocksCommon Lisp has 3 basic operators for creating blocks of
codeprognblocktagbody
If ordinary function calls are the leaves of a Lisp program, these operators are used to build the branches
![Page 3: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/3.jpg)
Control-Blocks> (progn
(format t “a”) (format t “b”) (+ 11 12) )ab23 -> only the value of the last expression is returned
![Page 4: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/4.jpg)
Control-Blocks> (block head
(format t “Here we go.”) (return-from head ‘idea) (format t “We’ll never see this.”))Here we go.IDEA
Calling return-from allows your code to make a sudden but graceful exit from anywhere in a body of code
Expressions after the return-from are not evaluated
![Page 5: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/5.jpg)
Control-Blocks> (block nil
(return 27))27
> (dolist (x ‘(a b c d e)) (format t “~A “ x) (if (eql x ‘c) (return ‘done)))A B CDONE
![Page 6: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/6.jpg)
Control-BlocksThe body of a function defined with defun is implicitly enclosed in
a block with the same name as the function(defun foo ( )
(return-from foo 27) )(defun read-integer (str)
(let ((accum 0)) (dotimes (pos (length str)) (let ((i (digit-char-p (char str pos)))) (if i (setf accum (+ (* accum 10) i)) (return-from read-integer nil)))) accum))
![Page 7: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/7.jpg)
Control-BlocksWithin tagbody, you can use go > (tagbody
(setf x 0) top (setf x (+ x 1)) (format t “~A “ x) (if (< x 10) (go top)))1 2 3 4 5 6 7 8 9 10
This operator is mainly something that other operators are built upon, not something you would use yourself
Ugly code!!
![Page 8: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/8.jpg)
Control-BlocksHow to decide which block construct to use?
Nearly all the time you’ll use prognIf you want to allow for sudden exits, use blockMost programmers will never use tagbody explicitly
![Page 9: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/9.jpg)
Control-Contextlet
Takes a body of codeAllows us to establish variables for use within the body> (let ((x 7)
(y 2)) (format t “Number”) (+ x y))Number9
![Page 10: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/10.jpg)
Control-Context> ((lambda (x) (+ x 1)) 3)
4((lambda (x y)
(format t “Number”) (+ x y))72)
![Page 11: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/11.jpg)
Control-ContextOne let-created variable can’t depend on other variables
created by the same let(let ((x 2)
(y (+ x 1))) (+ x y))
((lambda (x y) (+ x y)) 2 (+ x 1))
> (let* ((x 1) (y (+ x 1))) (+ x y))3
equivalent
![Page 12: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/12.jpg)
Control-ContextA let* is functionally equivalent to a series of nested lets(let ((x 1))
(let ((y (+ x 1))) (+ x y)))
In both let and let*, initial values default to nil> (let (x y)
(list x y))(NIL NIL)
![Page 13: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/13.jpg)
Control- Conditionals(if (oddp that)
(progn (format t “Hmm, that’s odd.”) (+ that 1)))
(when (oddp that) (format t “Hmm, that’s odd.”) (+ that 1))
equivalent
![Page 14: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/14.jpg)
Control- Conditionals(if <test> <then form> <else form>)(if <test> <then form>)
(when <test> <then form>)
(if <test> nil <else form>) (unless <test> <else form>)
![Page 15: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/15.jpg)
Control- Conditionals(defun our-member (obj lst)
(if (atom lst) nil (if (eql (car lst) obj) lst (our-member obj (cdr lst))))
(defun our-member (obj lst) (cond ((atom lst) nil) ((eql (car lst) obj) lst) (t (our-member obj (cdr lst)))))
equivalent
A Common Lisp implementation will probably implement cond by translating it to the “if” format
![Page 16: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/16.jpg)
Control- Conditionalscond
(cond (<test 1> <consequent 1-1> …) (<test 2> <consequent 2-1> …) … (<test m> <consequent m-1> …));cond
The conditions are evaluated in order until one of them returns trueWhen one condition returns true, the expressions associated with it are
evaluated in order, and the value of the last is returns as the value of the cond
> (cond (99)) ; if there are no expressions after the successful condition99 ; , the value of the condition itself is returned.
![Page 17: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/17.jpg)
Control- Conditionalscase
(case <key form> (<key 1> <consequent 1-1> …) (<key 2> <consequent 2-1> …) ... (<key m> <consequent m-1> …)) ;case
![Page 18: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/18.jpg)
Control- Conditionals(defun month-length (mon)
(case mon ((jan mar may jul aug oct dec) 31) ((apr jun sept nov) 30) (feb (if (leap-year) 29 28)) (otherwise “unknown month”)))
Keys Are treated as constants Will not be evaluated
> (case 99 (99)) The successful clause contains only keysNIL
![Page 19: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/19.jpg)
Control- Iterationdo
(do ((<parameter 1> <initial value 1> <update form 1>) (<parameter 2> <initial value 2> <update form 2>) … (<parameter n> <initial value n> <update form n>)) (<termination test> <intermediate forms, if any> <result form>) <body> ) ;do
> (let ((x ‘a)) (do ((x 1 (+ x 1)) (y x x)) ((> x 5)) (format t “(~A ~A) “ x y)))(1 A) (2 1) (3 2) (4 3) (5 4) ;on each iteration, x gets its previousNIL ;value plus 1; y also gets the previous ;value
![Page 20: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/20.jpg)
Control- Iterationdo*
Has the same relation to do as let* does to let> (do* ((x 1 (+ x 1))
(y x x)) ((> x 5)) (format t “(~A ~A) “ x y))(1 1) (2 2) (3 3) (4 4) (5 5)NIL
![Page 21: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/21.jpg)
Control- Iterationdolist
> (dolist (x ‘(a b c d) ‘done) (format t “~A “ x))A B C DDONE
dotimes> (dotimes (x 5 x) ; for x = 0 to 5-1, return x
(format t “~A “ x))0 1 2 3 4 5
![Page 22: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/22.jpg)
Control- Multiple valuesIn Common Lisp, an expression can return zero or more
valuesE.g., get-decoded-time returns the current time in nine
values value
Returns multiple values> (values ‘a nil (+ 2 4))
ANIL6
![Page 23: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/23.jpg)
Control- Multiple values> ((lambda ( )
(values 1 2) ))1;2
If something is expecting only one value, all but the first will be discarded> (let ((x (values 1 2)))
x)1
![Page 24: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/24.jpg)
Control- Multiple values> (values) returns no value> (let ((x (values)))
x)NIL
Use multiple-value-bind to receive multiple values> (multiple-value-bind (x y z) (values 1 2 3)
(list x y z))(1 2 3)
> (multiple-value-bind (x y z) (values 1 2) (list x y z))(1 2 NIL)
![Page 25: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/25.jpg)
Control- Multiple values> (multiple-value-bind (s m h) (get-decoded-time)
(format nil “~A:~A:~A” h m s))“4:32:13”
We can pass on multiple values as the arguments to a second function using multiple-value-call> (multiple-value-call #’+ (values 1 2 3))
6multiple-value-list is like using multiple-value-call with
#’list as the first argument> (multiple-value-list (values ‘a ‘b ‘c))
(A B C)
![Page 26: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/26.jpg)
Control-Abortscatch and throw
(defun super ( ) (catch ‘abort (sub) (format t “We’ll never see this.”)))(defun sub ( ) (throw ‘abort 99)> (super)99
![Page 27: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/27.jpg)
Control- Example: Date arithmetic(defconstant month #(0 31 59 90 120 151 181 212 243 273 304 334 365))(defconstant yzero 2000)(defun leap? (y) (and (zerop (mod y 4)) (or (zerop (mod y 400)) (not (zerop (mod y 100))))))
![Page 28: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/28.jpg)
Control- Example: Date arithmetic(defun date->num (d m y) (+ (- d 1) (month-num m y) (year-num y)))(defun month-num (m y) (+ (svref month (- m 1)) (if (and (> m 2) (leap? y)) 1 0)))(defun year-num (y) (let ((d 0)) (if (>= y yzero) (dotimes (i (- y yzero) d) (incf d (year-days (+ yzero i)))) (dotimes (i (- yzero y) (- d)) (incf d (year-days (+ y i)))))))(defun year-days (y) (if (leap? y) 366 365))
![Page 29: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/29.jpg)
Control- Example: Date arithmetic(defun num->date (n) (multiple-value-bind (y left) (num-year n) (multiple-value-bind (m d) (num-month left y) (values d m y))))(defun num-year (n) (if (< n 0) (do* ((y (- yzero 1) (- y 1)) (d (- (year-days y)) (- d (year-days y)))) ((<= d n) (values y (- n d)))) (do* ((y yzero (+ y 1)) (prev 0 d) (d (year-days y) (+ d (year-days y)))) ((> d n) (values y (- n prev))))))
![Page 30: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/30.jpg)
Control- Example: Date arithmetic(defun num-month (n y) (if (leap? y) (cond ((= n 59) (values 2 29)) ((> n 59) (nmon (- n 1))) (t (nmon n))) (nmon n)))(defun nmon (n) (let ((m (position n month :test #’<))) (values m (+ 1 (- n (svref month (- m 1)))))))(defun date+ (d m y n) (num->date (+ (date->num d m y) n)))
![Page 31: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/31.jpg)
Control- Example: Date arithmetic> (mapcar #’leap? ‘(1904 1900 1600))
(T NIL T)> (multiple-value-list (date+ 17 12 1997 60))
(15 2 1998)
![Page 32: Functional Programming](https://reader036.vdocuments.us/reader036/viewer/2022062520/56815fd3550346895dcecf8a/html5/thumbnails/32.jpg)
ControlHomework (Due April 7)
Rewrite month-mon to use case instead of svrefDefine a single recursive function that returns, as two
values, the maximum and minimum elements of a vector