Chapters 6 & 7
LISP (unlike Prolog) allows iteration
– mapcar, remove-if(-not), count-if, find-if for special purpose iteration
Dotimes, dolist & do allow more general iteration
– often used with side-effects
Do takes list of local variables, stopping condition plus return expression and body
> (do ((i 1 (1+ i)))
((> i 10) ‘done)
(format t “~a ” i))
1 2 3 4 5 6 7 8 9 10
DONE
Exponentiation function
– (power 5 3) => 125
(defun power (M N) extra form in defun just for the side effect
(setf result 1)
(dotimes (i N result) (setf result (* M result)))) loop control variable body of the loop upper bound of the loop return value done for the side effect
(dotimes (
<body> i N result
)
) for ( i = 0; i < N ; i ++ )
<body> return result ;
(dotimes (i N res)
(setf res (* M res))) for ( i = 0; i < N; i++) res = M * res; return res;
Loop control variable is not evaluated
Upper bound is evaluated before 1 st iteration
Return result is evaluated after last iteration
Body evaluated once per iteration
Loop control variable available in the loop
– just like loop control in imperative languages
(defun factorial (N)
(setf fact 1)
(dotimes (i N fact)
(setf fact (* (1+ i) fact))))
Need to add 1 to i, because i runs from 0 to N–1, not 1 to N
Write a function using dotimes to calculate the sum of the numbers from 1 to N
– can you do it without adding 1 to i each time?
(defun sum-to-N (N)
(setf sum 0)
(dotimes (i (1+ N) sum)
(setf sum (+ sum i))))
Run loop to N+1 so we get sum 0..N
– 0 adds nothing to the sum, so that’s OK
Alternative: (dotimes (i N (+ sum N))
…
)
vs.
Functions above use global variables
– not good – what if someone was using them already?
– what if one of the functions called uses the same global variable?
Would like all the variables to be local
LISP gives us let and let*
Let defines & initializes local variables
> (let ((v1 10) (v2 5)) (+ v1 v2))
15
> v1
ERROR: undefined variable
(let <list-of-variable-value-pairs> <body>)
– value of <body> becomes value of let
(defun power (M N)
(let ((result 1))
(dotimes (i N result) (setf result (* M result))))
result now local – no complications
Note: ((result 1))
– list of variable-value pairs
– each pair in its own list
Can use as many as you like
(defun correlation (X Y)
(let ((N (length X))
(Sx (sum-list X))
(Sy (sum-list Y))
(Sxy (dot-product X Y))
(Sxx (sum-of-squares X))
(Syy (sum-of-squares Y)))
(/ (– (* N Sxy) (* Sx Sy)) (*
…
)))))
Rewrite factorial and sum-to-N using lets
(defun factorial (N)
(setf fact 1)
(dotimes (i N fact) (setf fact (* (+ i 1) fact))))
(defun sum-to-N (N)
(setf sum 0)
(dotimes (i (+ N 1) sum) (setf sum (+ sum i))))
All assignments are done “at the same time”
– can’t use the value of one to set another
> (let ((x 5) (y (+ x 10))) … )
ERROR – unbound variable X
Won’t get an error if x is defined
– you’ll just get the other value of x
–
(let ((x 5) (y (+ x 10))) (+ x y)) => 796 (!!!)
“other” X was 781
In case you want to set one value based on another
> (let* ((x 5) (y (+ x 10))) (+ x y))
20
X is already a local variable by the time let* gets to it
DoList allows iteration over lists
– do something for each element of a list
– also usually with side-effects
(dolist (<var> <list> <result>) <body>)
– <var> set to each element of <list> in turn
– <body> evaluated for each value
– <result> evaluated & returned
(do-reverse ‘(1 2 3 4 5)) => (5 4 3 2 1)
(defun do-reverse (L)
(let ((rev ()))
(dolist (e L rev) (setf rev (cons e rev)))))
Elements added to front of rev
– rev = (), (cons 1 rev) => (1)
– rev = (1), (cons 2 rev) => (2 1)
> (defun sum-list (L)
(let ((sum 0))
(dolist (e L sum) (setf sum (+ sum e)))))
> (sum-list ‘(4 7 15)) sum
0 e
4, sum
(+ 0 4) => 4 e
7, sum
(+ 4 7) => 11 e
15, sum
(+ 11 15) => 26
=> sum => 26
Write the function do-intersect, to calculate the intersection of two lists using let and dolist
> (do-intersect ‘(1 3 5 7 9) ‘(3 6 9 12))
(9 3)
Iterate thru first list
– if current element is in second list, add it to the intersection
– intersection should have started as empty
(defun do-intersection (L1 L2)
(let ((inter ()))
(dolist (e L1 inter)
(when (member e L2) (push e inter)))))
Applications
– chapters 24 & 26