CSC153 2004S, Class 8: Local Bindings Admin: * Missing: Ilan, Andrew * Report from Minnesota * Questions on HW2? * Using libraries * Create a file called "library.scm" (or whatever) with all your favorite procedures * Load it with (load "library.scm") * HW1 to be returned this evening (I hope) * Did anyone write the fairly-quick exponentiation function using a loop? * Here's the slow one int expt(int base, int power) { int result = 1; for (int i = 0; i < power; i++) result *= base; return result; } // expt(int, int) * How about the faster one? int expt(int base, int power) { int result = 1; ... return result; } // expt(int, int) * Think about it for Wednesday * "How do I write variable-arity procedures?" * Use param rather than (param) after the lambda Overview: * Why have local variables? * Are local variables necessary? What alternatives are there? * Local bindings with let and let* * Lab Local variable: Named value that appear within procedures (or expressions) Why do we have local variables? * Efficiency: Don't have to recompute the same thing twice float sqrt-of-two = Math.sqrt(2); * Easier to read stuff (and understand complex sequences of operations) if you do things part by part (define list-of-e (list 'e)) (define list-of-de (list 'd (list-of-e))) * Because we actually have things we want to vary (e.g., a solution we update) * Variables can clarify intent println(3*Math.sqrt(x)+5); float stddev = Math.sqrt(variance); * Good names are important! * Ease of reading is important. * Efficiency is important. * Schemers don't like things to vary Can we obtain the gain in efficiency without using let? * Use procedures as values (forces naming of procedures) (define silly1 (lambda (x y) (+ (/ x (sqrt y)) (/ (sqrt y) x)))) (define silly2 (lambda (x y) (silly2-helper x (sqrt y)))) (silly2-helper (lambda (x sqrt-y) (+ (/ x sqrt-y) (/ sqrt-y x)))) The let construct lets you name values (let ((NAME1 EXP1) (NAME2 EXP2) ... (NAMEn EXPn)) BODY) Meaning: (1) Evaluate EXP1 .. EXPn (2) Updates the "name to value" table to associate each name with the corresponding value (3) Evaluates BODY in that new environment (4) Forgets everything it just learned (5) Returns the value of BODY To sequence the assignment of values to names, use let* instead of let. Each expression can then use the name from the previous expression. Do the lab! Reflection: * Takes some practice to get the parentheses right. * Can be used in individual expressions as well as in procedures * We'll discuss the ordering of let and lambda on Wednesday Homework: * Read and reflect on "Preconditions and Postconditions"