Scope: What’s in a Name? CMSC Introduction to Computer Programming October 16, 2002
Roadmap Recap: Procedural Abstraction –Procedures as Parameters: scale Unnamed Procedures: Lambda Scope –Bound and free variables –Local variables: With formal parameters With let Procedures as return values
Procedural Abstraction Goal: single point of control –Avoid copying and modifying code Identify similarities in procedures –E.g. differ only in some function Solution: Abstract, and pass differing procedure(s) as parameter –Example: map Doublelist, squarelist, etc,...
Scalelist (before abstraction) Observation1: Same pattern as squarelist, map Observation2: Defining scale-fn is silly Observation3: Where does scale get its value? (define (scalelist scale alon) (define (scale-fn x) (* x scale)) (cond ((null? alon) ‘()) (else (cons (scale-fn (car alon)) (scalelist (cdr alon)))))
Scalelist (after abstraction) (define (scalelist scale alon) (define (scale-fn x) (* scale x)) (map scale-fn alon))
Unnamed Functions: Lambda Issue: Defining lots of trivial procedures –E.g. add2, double, triple… Solution: unnamed function Can’t be recursive (lambda ( {.. }) exp) E.g. “Add2” (lambda (x) (+ x 2)) Apply like other procedures –((lambda (x) (+ x 2)) 10) -> 12
Redefining with Lambda (define (doublelist alon) (map (lambda (x) (+ x x)) alon)) (define (triplelist alon) (map ???? alon)) (define (scalelist scale alon) (map ???? alon))
(define (sum alist) (cond ((null? alist) 0) (else (+ (car alist) (sum (cdr alist)))) Abstraction with Sum & Product Product? General Pattern?
Observation 3: Value of Scale Lexical scope: –Variable binding: Parameters Binding occurrence: Formal parameter of procedure BINDS to value in procedure call Bound occurrence: Appearances of variable inside procedure def’n get value –“free” variable: Global scope: top-level define (define (scalelist scale alon) (define (scale-fn x) (* scale x)) (map scale-fn alon))
Scope Region where binding gives value –Nearest enclosing block with binding occurrence Renaming: –Consistently rename variable w/in scope Meaning is unchanged (define (square x) (* x x)) (define (double x) (+ x x)) –(define (double y) (+ y y)) No change in meaning; no effect on square..
Scope Examples (define (p1 x y) (+ (* x y) (+ (* 2 x) (+ (* 2 y) 22)))) (define (p2 x) (+ (* 55 x) (+ x 11))) (define (p3 x) (+ (p1 x 0) (+ (p1 x 1) (p2 x))))
Defining Local Variables with Let Local variables: –Store and name partial result –Avoid repeated computation if result reused –Make code more intelligible (let ((x 3) (y 4)) (* x y)) 12
Let example Reverse-and-double ‘((a b) (c d)) ->((b a) (b a) (d c) (d c) ) (define (reverse-and-double alist) (cond ((null? alist) ‘()) (else (cons (reverse (car alist)) (cons (reverse (car alist)) (reverse-and-double (cdr alist))))) Problems?????
Let Example Avoid repeated work (define (reverse-and-double alist) (cond ((null? alist) ‘()) (else (let ((reverse-first (reverse (car alist)) (reverse-rest (reverse-and-double (cdr alist)))) (cons (reverse-first (cons (reverse-first reverse-rest))))
Procedures as First-class Objects Can be: –Named by variables –Can be passed as arguments to functions –Can be included in data structures –Can be returned as the results of functions
Procedures as Results of Functions Class of procedures: –E.g. scale1, scale2, scale3… ---> scale-n (define (scale-n scaler) (lambda (x) (* x scaler))) (define scale3 (scale-n 3)) (scalelist scale3 ‘( )) ----> ( )
Summary Unnamed procedures Scope: –Variable binding Parameters as binding instances Naming local variables with let Returning procedures as results
Next Time Extended Example