CSC151 2010S, Class 20: Iteration Overview: * Why do we need both map and for-each? * Using map and for-each with multiple-parameter procedures * Lab Admin: * Oranges! Please use keyboard wipes after finishing your orange. * Reading for Monday: Local Bindings. * I am eliminating quizzes. * Assignment 5 is now ready. * I think today's lab goes quickly; if so, you may want to start the assignment afterwards. Random questions * Can we reuse procedure names? No * Can we reuse parameter names across procedures? Yes * What happens when an anonyous procedure has a parameter that matches the name of the parameter of an enclosing procedure? THE OUTER PARAMETER GETS HIDDEN (define foo (lambda (x) (map (lambda (x) ...) ...))) (define foo (lambda (x) (map (lambda (n) (+ x (square n))) (iota 5)))) ; For (foo 4) we expect to get ; A list of length 5 ; With values (4 5 8 13 20) (define bar (lambda (x) (map (lambda (x) (+ x (square x))) (iota 5)))) ; For (bar 4) we expect to get (0 2 6 12 20) ; And the outermost x is never used. * NOTE: A variable refers to the closest binding lambda * Can my anonymous procedures use the parameters of the outer procedures? YES (define bar (lambda (x) (map (lambda (n) (* n x)) ...))) (define foo (lambda (x y z) (map (lambda (q r) (* x y ...) * How do we combine two lists? (append lst1 lst2) ---- For-each and map * for-each is a lot like map (map proc lst) (for-each proc lst) * Both apply a procedure to each element of a list * How do they differ? * In intent * map returns a list - the primary goal of map is to build new lists from old * for-each doesn't return a list - the primary goal of for-each is to do a side-effecting operation on each element of the list * In guaranteed processing order * for-each always processes the list from left to right * map can do the elements in any order * In likely ways to write * We tend to nest maps * We can't nest for-each Problem: I want to use a binary procedure with map or for-each * E.g., (define action1! (lambda (turtle n) (turtle-forward! turtle n) (turtle-turn! turtle n))) * "For each value between 0 and 11, run action1! with tommy." (for-each action1! (iota 12)) * Three possible strategies: * Build one or more additional lists, one list for each additional parameter. (for-each action1! (make-list tommy 12) (iota 12)) * Write an anonymous function that fills in the extra parameters (for-each (lambda (n) (action1! tommy n)) (iota 12)) * We so frequently turn two-parameter procedures into one-parameter procedures that we have additional functions to do that (for-each (l-s action1! tommy) (iota 12)) * "For each turtle, run action1! with an N of 15" (for-each (lambda (turtle) (action1! turtle 15)) (list tommy tonya tucker michaelangelo)) (for-each (r-s action! 15) (list tommy tonya tucker michaelangelo)) Suppose we want to increment and square each number from 0 to N-1. * Increment means "add 1". There is a procedure called increment, but we can also use (+ 1 ...) (define whatever (lambda (n) (map square (map increment (iota n))))) (define whatever (lambda (n) (map (o square increment) (iota n)))) (define whatever (lambda (n) (map (o square (l-s + 1)) (iota n)))) (define whatever (define whatever (lambda (n) (map (lambda (i) (square (+ i 1))) (iota n))))