; Iteration ; - doing a sequence of steps , either n times, or until some exit condition is met ; - in contrast to recursion, one call to an iterative procedure will cause many ; steps to be done ; - just as recursion is the major form of compuation in Scheme, iteration is ; the major form of computation for langauges like C, C++, Java, .... ; - for our practical purposes, we can think of Scheme's iteration syntax ; as a shorthand for what we have been doing the last couple days, that is ; having the kernel keep track of a variable like POS and modify it each time ; and stop when it reaches a certain value ; syntax for iteration in Scheme, the following is an expression , like a letrec or cond ;(do LOOP-CONTROL-LIST ; (EXIT-TEST POSTLUDE) ; BODY) ; note that some of these parts could be empty, typically either postlude or body ; LOOP-CONTROL-LIST is a list of three element lists, that are similar to ; the binding list for a named let, note that the INIT-VAL's and UPDATE-VAL's ; can be any Scheme expression ; ((VAR1 INIT-VAL1 UPDATE-VAL1) (VAR2 INIT-VAL2 UPDATE-VAL2) ....) ; EXIT-TEST is a boolean expression that when true means it is time to stop ; POSTLUDE is either what we return when the do expression finishes, or it ; can be one last side-effect, this could be empty ; BODY is where we execute side-effect commands at each step of the loop ; so vector-set! might be done here...., it there are no side effects or we are not ; returning a vector, this too may be empty ; no let us write double-vector-elements! with iteration ; this will change the input vector, so that all of its elements are doubled (define double-vector-elements! (lambda (vec) (do ((pos (- (vector-length vec) 1) (- pos 1))) ; loop-control-list ((< pos 0) ) ; since procedure returns nothing, postlude is empty (vector-set! vec pos (* 2 (vector-ref vec pos)))) ; body )) ; note that most anything we have done in the past with recursion, can be done with ; iteration ; recall the procedure two-power, which took in a natural number n and returned 2^n ; here is how we could write it with iteration (define two-power (lambda (n) (do ((remaining n (- remaining 1)) ; if we want to compute something that is not a vector, we are pretty much ; forced to do it in the loop-control-list ; here we will keep track of our partial answer in a variable called result (result 1 (* result 2))) ((zero? remaining) result) ) ; the body is empty because we are not using side-effects like vector-set! )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; day 2 ; note that if you are using more than one loop control variable (and typically ; you will be if you are not returning a vector, like when you compute vector-sum) ; then the loop control variables are updated "simultaneously" so you cannot ; refer to one loop control variable when initializing another one, but you can ; refer to other loop control variables during updates.... ; one other thing, it is reasonably straightforward to translate a tail recursive ; procedure to one that uses iteration, you should make the loop control variables ; the same as the ones passed by the kernel ; here is an example of Fibonacci using iteration ; first let's look at the tail recursive version... ;(define Fibonacci ; (lambda (n) ; (Fibonacci-kernel 0 1 n))) ; initialize loop control ; ;(define Fibonacci-kernel ; (lambda (current next remaining) ; define loop control ; (if (= 0 remaining) ; exit test ; current ; postlude ; (Fibonacci-kernel next (+ current next) (- remaining 1))))) ; update loop control (define Fibonacci (lambda (n) (do ((current 0 next) (next 1 (+ current next)) (remaining n (- remaining 1))) ((= 0 remaining) current) )))