Local definitions and lexical scope Readings: HtDP , Intermezzo 3 - - PDF document

local definitions and lexical scope
SMART_READER_LITE
LIVE PREVIEW

Local definitions and lexical scope Readings: HtDP , Intermezzo 3 - - PDF document

Local definitions and lexical scope Readings: HtDP , Intermezzo 3 (Section 18). Language level: Intermediate Student Topics: Motivating local definitions Semantics of local Reasons to use local Terminology Motivation Semantics Reasons


slide-1
SLIDE 1

Local definitions and lexical scope

Readings: HtDP , Intermezzo 3 (Section 18). Language level: Intermediate Student Topics: Motivating local definitions Semantics of local Reasons to use local Terminology

Motivation Semantics Reasons Terminology

1/39 12: Local Definitions CS 135

Local definitions

The functions and special forms we’ve seen so far can be arbitrarily nested—except define and check-expect. So far, definitions have to be made “at the top level”, outside any expression. The Intermediate language provides the special form local, which contains a series of local definitions plus an expression using them.

(local [(define x_1 exp_1) ... (define x_n exp_n)] bodyexp)

What use is this?

Motivation Semantics Reasons Terminology

2/39 12: Local Definitions CS 135

Motivating local definitions

Consider Heron’s formula for the area of a triangle with sides a, b, c:

  • s(s − a)(s − b)(s − c), where s = (a + b + c)/2

It is not hard to create a Racket function to compute this function, but it is difficult to do so in a clear and natural fashion. We will describe several possibilities, starting with a direct implementation.

Motivation Semantics Reasons Terminology

3/39 12: Local Definitions CS 135

slide-2
SLIDE 2

> Motivation: direct translation

(define (t-area-v0 a b c) (sqrt (* (/ (+ a b c) 2) (- (/ (+ a b c) 2) a) (- (/ (+ a b c) 2) b) (- (/ (+ a b c) 2) c))))

The repeated computation of s = (a + b + c)/2 is awkward.

Motivation Semantics Reasons Terminology

4/39 12: Local Definitions CS 135

> Motivation: rewrite expressions

We could notice that s − a = (−a + b + c)/2, and make similar substitutions.

(define (t-area-v1 a b c) (sqrt (* (/ (+ a b c) 2) (/ (+ (- a) b c) 2) (/ (+ a (- b) c) 2) (/ (+ a b (- c)) 2))))

This is slightly shorter, but its relationship to Heron’s formula is unclear from just reading the code, and the technique does not generalize.

Motivation Semantics Reasons Terminology

5/39 12: Local Definitions CS 135

> Motivation: use a helper function (v1)

We could instead use a helper function.

(define (t-area-v2 a b c) (sqrt (* (s a b c) (- (s a b c) a) (- (s a b c) b) (- (s a b c) c)))) (define (s a b c) (/ (+ a b c) 2))

This generalizes well to formulas that define several intermediate quantities. But the helper functions need parameters, which again makes the relationship to Heron’s formula hard to

  • see. And there’s still repeated code

and repeated computations.

Motivation Semantics Reasons Terminology

6/39 12: Local Definitions CS 135

slide-3
SLIDE 3

> Motivation: use a helper function (v2)

We could instead move the computation with a known value of s into a helper function, and provide the value of s as a parameter.

(define (t-area/s a b c s) (sqrt (* s (- s a) (- s b) (- s c)))) (define (t-area-v3 a b c) (t-area/s a b c (/ (+ a b c) 2)))

This is more readable, and shorter, but it is still awkward. The value of s is defined in one function and used in another.

Motivation Semantics Reasons Terminology

7/39 12: Local Definitions CS 135

> Motivation: use local

The local special form we introduced provides a natural way to bring the definition and use together.

(define (t-area-v4 a b c) (local [(define s (/ (+ a b c) 2))] (sqrt (* s (- s a) (- s b) (- s c)))))

This is nice and short! It looks like Heron’s formula. No repeated code or computations.

Motivation Semantics Reasons Terminology

8/39 12: Local Definitions CS 135

Since local is another special form (like

cond) that results in double parentheses,

we will use square brackets to improve

  • readability. This is another convention.

Semantics of local

Local definitions permit reuse of names. This is not new to us:

(define n 10) (define (myfn n) (+ 2 n)) (myfn 6)

gives the answer 8, not 12. The substitution specified in the semantics of function application ensures that the correct value is used while evaluating the last line.

Motivation Semantics Reasons Terminology

9/39 12: Local Definitions CS 135

slide-4
SLIDE 4

> Reusing names

The name of a formal parameter to a function may reuse (within the body of that function) a name which is bound to a value through define. Similarly, a define within a local expression may rebind a name which has already been bound to another value or expression. The substitution rules we define for local as part of the semantic model must handle this. The resulting substitution rule for local is the most complicated one we will see in this course.

Motivation Semantics Reasons Terminology

10/39 12: Local Definitions CS 135

> Informal substitution rule for local

The substitution rule works by replacing every name defined in the local with a fresh name (a.k.a. fresh identifier) – a new, unique name that has not been used anywhere else in the program. Each old name within the local is replaced by the corresponding new name. Because the new name hasn’t been used elsewhere in the program, the local definitions (with the new name) can now be “promoted” to the top level of the program without affecting anything outside of the local. We can now use our existing rules to evaluate the program. The next slide shows an example (the last version of Heron’s formula). Then we’ll state the rule more rigourously.

Motivation Semantics Reasons Terminology

11/39 12: Local Definitions CS 135

> Example: evaluating t-area4

We’ll need a fresh identifier to replace s. We’ll use s_47, which we just made up.

(t-area4 3 4 5) ⇒ (local [(define s (/ (+ 3 4 5) 2))] (sqrt (* s (- s 3) (- s 4) (- s 5)))) ⇒ (define s_47 (/ (+ 3 4 5) 2)) (sqrt (* s_47 (- s_47 3) (- s_47 4) (- s_47 5))) ⇒ (define s_47 (/ 12 2)) (sqrt (* s_47 (- s_47 3) (- s_47 4) (- s_47 5))) ⇒ (define s_47 6) (sqrt (* s_47 (- s_47 3) (- s_47 4) (- s_47 5))) ⇒ ... 6

Motivation Semantics Reasons Terminology

12/39 12: Local Definitions CS 135

slide-5
SLIDE 5

> Substitution rule for local

In general, an expression of the form

(local [(define x_1 exp_1) ... (define x_n exp_n)] bodyexp)

is handled as follows:

x_i is replaced with a fresh identifier (call it x_i_new) everywhere in the local

expression, for 1 ≤ i ≤ n. The definitions (define x_1_new exp_1) ... (define x_n_new exp_n) are then lifted out (all at once) to the top level of the program, preserving their

  • rdering.

What remains looks like (local [] bodyexp'), where bodyexp' is the rewritten version of bodyexp. Replace the local expression with bodyexp'. All of this (the renaming, the lifting, and removing the local with an empty definitions list) is a single step.

Motivation Semantics Reasons Terminology

13/39 12: Local Definitions CS 135

> Revising function substitution

Our previous statement about using

  • ur existing rules isn’t quite correct.

Consider the code on the right. Where is 2 substituted for x?

(define (foo x y) (local [(define x y) (define z (+ x y))] (+ x z))) (foo 2 3) (f v_1 ... v_n) ⇒ exp' where (define (f x_1 ... x_n) exp) occurs to the left,

and exp' is obtained by substituting into the expression exp, with all occurrences

  • f the formal parameter x_i replaced by the value v_i (for i from 1 to n) except

where x_1 has been redefined within exp (e.g. within a local).

Motivation Semantics Reasons Terminology

14/39 12: Local Definitions CS 135

Reasons to use local

Clarity: Naming subexpressions Efficiency: Avoid recomputation Encapsulation: Hiding stuff Scope: Reusing parameters

Motivation Semantics Reasons Terminology

15/39 12: Local Definitions CS 135

slide-6
SLIDE 6

> Clarity: naming subexpressions

A subexpression used twice within a function body always yields the same value. Using local to give the reused subexpression a name improves the readability of the code. This was a motivating factor in t-area. Naming the subexpression made the relationship to Heron’s Formula clear.

(define (t-area-v4 a b c) (local [(define s (/ (+ a b c) 2))] (sqrt (* s (- s a) (- s b) (- s c)))))

Motivation Semantics Reasons Terminology

16/39 12: Local Definitions CS 135

> Clarity: mnemonic names

Sometimes we choose to use local in order to name subexpressions mnemonically to make the code more readable, even if they are not reused. This may make the code longer.

(define-struct coord (x y)) (define (distance p1 p2) (sqrt (+ (sqr (- (coord-x p1) (coord-x p2))) (sqr (- (coord-y p1) (coord-y p2)))))) (define (distance p1 p2) (local [(define delta-x (- (coord-x p1) (coord-x p2))) (define delta-y (- (coord-y p1) (coord-y p2)))] (sqrt (+ (sqr delta-x) (sqr delta-y)))))

Motivation Semantics Reasons Terminology

17/39 12: Local Definitions CS 135

Exercise 1

Write a function (sum-odds-or-evens L) that consumes a (listof Int). If there are more evens than odds, the function returns the sum of the evens. Otherwise, it returns the sum of the odds. Start by creating a local constant that contains a list of even numbers, and another that contains a list of odd numbers.

(sum-odds-or-evens '(1 3 5 20 30)) ⇒ 9

slide-7
SLIDE 7

> Efficiency: avoid recomputation

Recall that in lecture module 09, we saw a version of max-list used the same recursive application twice. The repeated computation of values caused it to be very slow, even for lists of length 25. We can use local to avoid recomputation.

Motivation Semantics Reasons Terminology

18/39 12: Local Definitions CS 135

» Efficiency: max-list without local

;; (max-list lon) produces the maximum element of lon ;; max-list: (listof Num) → Num ;; requires: lon is nonempty ;; Examples: (check-expect (max-list '(6 2 3 7 1)) 7) (define (max-list lon) (cond [(empty? (rest lon)) (first lon)] [(> (first lon) (max-list (rest lon))) (first lon)] [else (max-list (rest lon))]))

Motivation Semantics Reasons Terminology

19/39 12: Local Definitions CS 135

» Efficiency: max-list with local

;; (max-list3 lon) produces the maximum element of lon ;; max-list3: (listof Num) → Num ;; requires: lon is nonempty (define (max-list3 lon) (cond [(empty? (rest lon)) (first lon)] [else (local [(define max-rest (max-list2 (rest lon)))] (cond [(> (first lon) max-rest) (first lon)] [else max-rest]))]))

Motivation Semantics Reasons Terminology

20/39 12: Local Definitions CS 135

slide-8
SLIDE 8

» Efficiency: search-bt-path: original

;; search-bt-path-v1: Nat BT → (anyof false (listof Sym)) (define (search-bt-path-v1 k tree) (cond [(empty? tree) false] [(= k (node-key tree)) '()] [(list? (search-bt-path-v1 k (node-left tree))) (cons 'left (search-bt-path-v1 k (node-left tree)))] [(list? (search-bt-path-v1 k (node-right tree))) (cons 'right (search-bt-path-v1 k (node-right tree)))] [else false]))

Motivation Semantics Reasons Terminology

21/39 12: Local Definitions CS 135

» Efficiency: search-bt-path: helper function

;; search-bt-path-v2: Nat BT → (anyof false (listof Sym)) (define (search-bt-path-v2 k tree) (cond [(empty? tree) false] [(= k (node-key tree)) '()] [else (choose-path-v2 (search-bt-path-v2 k (node-left tree)) (search-bt-path-v2 k (node-right tree)))])) (define (choose-path-v2 path1 path2) (cond [(list? path1) (cons 'left path1)] [(list? path2) (cons 'right path2)] [else false]))

Motivation Semantics Reasons Terminology

22/39 12: Local Definitions CS 135

» Efficiency: search-bt-path: with local

;; search-bt-path-v3: Nat BT → (anyof false (listof Sym)) (define (search-bt-path-v3 k tree) (cond [(empty? tree) false] [(= k (node-key tree)) '()] [else (local [(define left (search-bt-path-v3 k (node-left tree))) (define right (search-bt-path-v3 k (node-right tree)))] (cond [(list? left) (cons 'left left)] [(list? right) (cons 'right right)] [else false]))]))

Motivation Semantics Reasons Terminology

23/39 12: Local Definitions CS 135

slide-9
SLIDE 9

» Efficiency: search-bt-path: with local

This new version of search-bt-path avoids making the same recursive function application twice, and does not require a helper function. But it still suffers from an inefficiency: we always explore the entire binary tree, even if the correct solution is found immediately in the left subtree. We can avoid the extra search of the right subtree using nested locals.

Motivation Semantics Reasons Terminology

24/39 12: Local Definitions CS 135

» Efficiency: search-bt-path: with nested local

;; search-bt-path-v4: Nat BT → (anyof false (listof Sym)) (define (search-bt-path-v4 k tree) (cond [(empty? tree) false] [(= k (node-key tree)) '()] [else (local [(define left (search-bt-path-v4 k (node-left tree)))] (cond [(list? left) (cons 'left left)] [else (local [(define right (search-bt-path-v4 k (node-right tree)))] (cond [(list? right) (cons 'right right)]

Motivation Semantics Reasons Terminology

25/39 12: Local Definitions CS 135

Exercise 2

Write a function (normalize L) that consumes a (listof Num), and returns the list containing each value in L divided by the sum of the values in L. Use only local helper functions, and compute the sum only once.

(normalize (list 4 2 14)) ⇒ (list 0.2 0.1 0.7)

slide-10
SLIDE 10

> Encapsulation: hiding stuff

Encapsulation is the process of grouping things together in a “capsule”. We have already seen data encapsulation in the use of structures. There is also an aspect of information hiding to encapsulation which we did not see with structures. The local bindings are not visible (have no effect) outside the local expression. In CS 246 we will see how objects combine data encapsulation with another type

  • f encapsulation we now discuss.

Motivation Semantics Reasons Terminology

26/39 12: Local Definitions CS 135

» Behaviour encapsulation

Local definitions can bind names to functions as well as values. Evaluating the local expression creates new, unique names for the functions just as for the values. This is known as behaviour encapsulation. Behaviour encapsulation allows us to move helper functions within the function that uses them, so they: are invisible outside the function. do not clutter the “namespace” at the top level. cannot be used by mistake. This makes the organization of the program more obvious and is particularly useful when using accumulators.

Motivation Semantics Reasons Terminology

27/39 12: Local Definitions CS 135

» Example: sum-list

(define (sum-list lon) (local [(define (sum-list/acc lst sofar) (cond [(empty? lst) sofar] [else (sum-list/acc (rest lst) (+ (first lst) sofar))]))] (sum-list/acc lon 0)))

Making the accumulatively-recursive helper function local facilitates reasoning about the program.

HtDP (section VI) discusses reasoning with invariants. It will be discussed further in CS

  • 245. It is important in CS 240 and CS 341.

Motivation Semantics Reasons Terminology

28/39 12: Local Definitions CS 135

slide-11
SLIDE 11

» Example: Insertion sort

(define (isort lon) (local [(define (insert n slon) (cond [(empty? slon) (cons n empty)] [(<= n (first slon)) (cons n slon)] [else (cons (first slon) (insert n (rest slon)))]))] (cond [(empty? lon) empty] [else (insert (first lon) (isort (rest lon)))])))

Motivation Semantics Reasons Terminology

29/39 12: Local Definitions CS 135

» Encapsulation and the design recipe

A function can enclose the cooperating helper functions that it uses inside a local, as long as these are not also needed by other functions. When this happens, the enclosing function and all the helpers act as a cohesive unit. Here, the local helper functions require contracts and purposes, but not examples

  • r tests. The helper functions can be tested by writing suitable tests for the

enclosing function. Make sure the local helper functions are still tested completely!

Motivation Semantics Reasons Terminology

30/39 12: Local Definitions CS 135

» Design recipe example

;; Full Design Recipe for isort ... (define (isort lon) (local [;; (insert n slon) inserts n into slon, preserving the order ;; insert: Num (listof Num) → (listof Num) ;; requires: slon is sorted in nondecreasing order (define (insert n slon) (cond [(empty? slon) (cons n empty)] [(<= n (first slon)) (cons n slon)] [else (cons (first slon) (insert n (rest slon)))]))] (cond [(empty? lon) empty] [else (insert (first lon) (isort (rest lon)))])))

Motivation Semantics Reasons Terminology

31/39 12: Local Definitions CS 135

slide-12
SLIDE 12

> Scope: reusing parameters

Making helper functions local can reduce the need to have parameters “go along for the ride”.

(define (countup-to n) (countup-to-from n 0)) (define (countup-to-from n m) (cond [(> m n) empty] [else (cons m (countup-to-from n (add1 m)))]))

Motivation Semantics Reasons Terminology

32/39 12: Local Definitions CS 135

» Example: countup-to

(define (countup-to-v2 n) (local [(define (countup-from m) (cond [(> m n) empty] [else (cons m (countup-from (add1 m)))]))] (countup-from 0))) n no longer needs to be a parameter to countup-from, because it is in scope.

If we evaluate (countup-to-v2 10) using our substitution model, a renamed version of countup-from with n replaced by 10 is lifted to the top level. Then, if we evaluate (countup-to-v2 20), another renamed version of

countup-from is lifted to the top level.

Motivation Semantics Reasons Terminology

33/39 12: Local Definitions CS 135

» Example: mult-table

We can use the same idea to localize the helper functions for mult-table from lecture module 08. Recall that

(mult-table 3 4) ⇒ (list (list 0 0 0 0) (list 0 1 2 3) (list 0 2 4 6))

The cth entry of the r th row (numbering from 0) is r × c.

Motivation Semantics Reasons Terminology

34/39 12: Local Definitions CS 135

slide-13
SLIDE 13

» mult-table: original

;; mult-table: Nat Nat → (listof (listof Nat)) (define (mult-table nr nc) (rows-to 0 nr nc)) ;; (rows-to r nr nc) produces mult. table, rows r...(nr-1) ;; rows-to: Nat Nat Nat → (listof (listof Nat)) (define (rows-to r nr nc) (cond [(>= r nr) empty] [else (cons (cols-to 0 r nc) (rows-to (add1 r) nr nc))])) ;; (cols-to c r nc) produces entries c...(nc-1) of rth row of mult. table ;; cols-to: Nat Nat Nat → (listof Nat) (define (cols-to c r nc) (cond [(>= c nc) empty] [else (cons (* r c) (cols-to (add1 c) r nc))]))

Motivation Semantics Reasons Terminology

35/39 12: Local Definitions CS 135

» mult-table: with local

(define (mult-table2 nr nc) (local [;; (rows-to r nr nc) produces mult. table, rows r...(nr-1) ;; rows-to: Nat Nat Nat → (listof (listof Nat)) (define (rows-to r) (cond [(>= r nr) empty] [else (cons (cols-to 0 r) (rows-to (add1 r)))])) ;; (cols-to c r nc) produces entries c...(nc-1) of rth row ;; cols-to: Nat Nat Nat → (listof Nat) (define (cols-to c r) (cond [(>= c nc) empty] [else (cons (* r c) (cols-to (add1 c) r))])) ] (rows-to 0)))

Motivation Semantics Reasons Terminology

36/39 12: Local Definitions CS 135

We will revisit this code again in M13.

Terminology associated with local

The binding occurrence of a name is its use in a definition, or formal parameter to a function. The associated bound occurrences are the uses of that name that correspond to that binding. The lexical scope of a binding occurrence is all places where that binding has effect, taking note of holes caused by reuse of names. Global scope is the scope of top-level definitions.

Motivation Semantics Reasons Terminology

37/39 12: Local Definitions CS 135

slide-14
SLIDE 14

Conclusions

The use of local has permitted only modest gains in expressivity and readability in our examples. The language features discussed in the next module expand this power considerably. Some other languages (C, C++, Java) either disallow nested function definitions or allow them only in very restricted circumstances. Local variable and constant definitions are more common.

Motivation Semantics Reasons Terminology

38/39 12: Local Definitions CS 135

Goals of this module

You should understand the syntax, informal semantics, and formal substitution semantics for the local special form. You should be able to use local to avoid repetition of common subexpressions, to improve readability of expressions, and to improve efficiency of code. You should understand the idea of encapsulation of local helper functions. You should be able to match the use of any constant or function name in a program to the binding to which it refers.

Motivation Semantics Reasons Terminology

39/39 12: Local Definitions CS 135