ITERATIVE CONSTRUCTS: DOLIST Dolist is an iterative construct (a loop statement) consisting of a variable declaration and a body The body states what happens.
Published byModified over 4 years ago
Presentation on theme: "ITERATIVE CONSTRUCTS: DOLIST Dolist is an iterative construct (a loop statement) consisting of a variable declaration and a body The body states what happens."— Presentation transcript:
ITERATIVE CONSTRUCTS: DOLIST Dolist is an iterative construct (a loop statement) consisting of a variable declaration and a body The body states what happens on each iteration of the loop The variable declaration creates a variable (sort of like a counter variable in a for loop) and specifies a list of values that the variable will be given (one value for each iteration of the loop). The variable declaration also specifies the value that will be returned when the dolist function ends. (dolist (var ‘(value1 value2 value3) ‘return-value ) (do-something var) )
DOLIST EXAMPLE A different way of having a particular computation applied to all the elements of a list: > (dolist (x ‘(1 2 3 4 5 6) ‘t) (cond ((evenp x) (print x))) ) 2 4 6 t Here, X is the local variable, (1 2 3 4 5 6) is the list to be scanned, ‘t is the result of the expression (returned when the dolist ends); there is only one statement in the body, to be executed for each value of X: there could be more!
Another DOLIST example Collecting up values in a DOLIST: suppose we want to add up all the even numbers in our list, so if the list is ‘(1 2 3 4 5 6 7 8) we’ll get 2+4+6+8=20 as our answer. Here’s a DOLIST for this: (let ((sum 0) ) (dolist (x ‘(1 2 3 4 5 6 7 8) sum) (cond ( (evenp x) (setf sum (+ sum x)) ) ) ) ) Notice that the value returned when this ends will be sum ! This example uses a number things we’ve seen before: let (to set up a storage variable), setf (to change the value of that variable), and the dolist.
DOTIMES DOTIMES allows the repetition of a computation a fixed number of times. As with DOLIST, its arguments are a variable declaration and a body. In DOTIMES, the variable is a counter whose value starts at 0 and which increments until it hits the specified stopping value. For each value of the counter, the body of the DOTIMES is executed. When the counter hits the stop-value, the specified return-value is returned as the value of the expression. (dotimes (counter stop-value return-value ) (do-something var) )
DOTIMES example > (dotimes (c 4 ‘done) (print (“Counter = “) (print c)) This piece of lisp will repeat the body (the two print statements) four times (c=0 to c=3). When the loop ends, the value ‘done will be returned. Counter = 0 Counter = 1 Counter = 2 Counter = 3 done
DOTIMES for factorial Recall that factorial N = N*(N-1)*(N-2)…1 We saw a recursive statement of factorial in our 2 nd lecture: (defun factorial(N) (if (= N 0) 1 (* N (factorial (- N 1))) )) Here’s an iterative version of factorial: (defun iterativeFactorial(N) (let ( (result 1) ) (dotimes (count (+ N 1) result) (setf result (* result count)) ) ) )
LOOP The loop command takes no arguments, apart from the sequence of expressions which form the body of the iteration: (loop (let ((value (read))) (cond ((null value) (return)) (t (print value)) ) Body of the loop (read) is a built-in function that reads a value from the user. This piece of code will simply echo whatever the user types in.
RETURN The return statement is for exiting from any iteration other than at the natural termination of the looping or passing results back from an iteration We can use return in DOLIST or DOTIMES if we want, or in any other iterative construct. In the LOOP expression, we have to use RETURN to end the loop (LOOP has no predefined check statement for loop finish).
DO iterative construct DO is more complicated than the the other iterative constructs DOLIST and DOTIMES IN a DO statement we can have a list of variables, each of which takes on a different value on each iteration of the loop. Each variable declaration in a DO consists of a list: ( variable-name initial-value computed-new-value ) Overall a DO expression has three parts: –A list of variable declarations as above (a list of lists) –A (finished-yet? return-value) pair, to check if the loop is over yet –A body (although in many DO expressions, no body is needed since most of the work is done in computing the new values for variables)
DO (defun average (L) (do ( (sum 0.0 (+ sum (first values))) (count 0 (+ count 1)) (values L (rest values)) ) ; initial values and updates for variables in do-loop ( (null values) (/ sum count) ) ; finished? test and result returned ); end of do-loop (no body) ); end of function In this function, the variable values starts out holding the input list L. On each iteration of the loop values becomes (rest values). The loop continues until (null values) is true. On each cycle of the loop, the number in (first values) is added to the sum variable, and the count variable goes up by one. When the loop finishes, we return (/ sum count) as the average of the numbers in the list.
Iteration vs. Recursion Scanning all the elements in a list: MAPC (if no results to be returned). MAPCAR (if results to be returned); or DOLIST Repeating a computation a number of times: DOTIMES, DO Repeating until some condition is met: DO and LOOP Testing whether some condition is met for elements in the list. ?
EXERCISE How would you write the function REMOVE-ITERATIVE, given a data-item X and a list L as arguments, that returns a list which is the same as L except that any items equal to X do not appear in this new list using DO rather than recursion? This will involve carefully coding how the variables in the DO expression get their new values on each iteration of the loop. Two variables: –values : holding the input list initially, and going down that list one element at a time using rest, as in our previous example –Answer : holding nothing initially. On each iteration of the loop, looking at the first element of values, and if that element is not the one we are trying to remove, setting answer to be (cons (first values) answer) That is, adding the value to the answer list. When do we stop? What answer do we return?
Remove-iterative (Defun remove-iterative(X L) (do ( ( (values L (rest values) ) ( (answer ‘() ) ) ( (null values) answers) ) ) (if (not (equal (first values) x)) (cons (first values) answer) answer) In this function, all the work is done by the if which decides whether to add the first element of the values list to the answer or not, depending on whether it is equal to the element X that to be removed.
EXERCISE The following pattern of numbers is called Pascal’s triangle: The numbers at the edge of the triangle are all 1 and each number inside the triangle is the sum of the two numbers above it. Write a procedure that computes elements of Pascal’s triangle by means of a recursive process. 1 11 112 1133 11446