Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

A function definition introduces a new local scope - the parameters are defined within the body.

...

(define (parameters...)
body)

...

A local definition
introduces a new local scope - the names in the definitions are defined
within both within the bodies of the definitions and within the
local's body.

...

(local definitions...
body)

...

Wiki Markup
Note that the use of square brackets

 \[ \]

 here is equivalent

 to parentheses( )

.  The brackets help set off the definitions

 a little more clearly for readability.

...

...

In order to uselocaland use local and the other features about
to be introduced in class, you need to set the DrScheme language level to
"Intermediate".

...

Exercises

HTML
HTML

Finding the maximum element of a list

...

.
Here are two easy ways to misuselocal:

HTML
HTML
HTML

Wiki Markup
; max-of-list: non-empty-list \-> number


(define (max-of-list a-nelon)


(local [(define max-rest (max-of-list (rest a-nelon)))

(cond
|(define max-rest (max-of-list (rest a-nelon)))]
(cond [(empty? (rest a-nelon)) (first a-nelon)|(empty? (rest a-nelon)) (first a-nelon)

]
\[else  (cond [(< (first a-nelon) max-rest) max-rest

]
[else (first a-nelon)|else (first a-nelon)])\])))

HTML
HTML
HTML

Question

HTML
HTML

...

Make sure you don't put alocaltoo early in your code.

HTML
HTML
HTML

Wiki Markup
; max-of-list: non-empty-list \-> number


(define (max-of-list a-nelon)


(cond [(empty? (rest a-nelon)) (first a-nelon)

[else (local
|(empty? (rest a-nelon)) (first a-nelon)]
\[else  (local \[(define max-rest (max-of-list (rest a-nelon)))


(define first-smaller? (< (first a-nelon) max-rest))\]


(cond [first-smaller? max-rest

else (first
|first-smaller? max-rest]
[else (first a-nelon)|else (first a-nelon)]))\]))

HTML

This isn't wrong, but the local definition offirst-smaller?
is unnecessary. Since the comparison is only used once,
this is not a case of code reuse or recomputation.
It provides a name to a part of the computation,
but whether that improves clarity in this case is a judgement call.

...

(define x 5)
(define x^ 7)
x^

HTML

Example:

HTML

Wiki Markup
(define x 5)


(define y x)


(define z (\+ x y))


(local \[(define x 7)


(define y x)\]


(\+ x y z))

(define x 5)
(define y x)
(define z (+ x y))
(define x^ 7)
(define y^ x^)
(+ x^ y^ z)

...

As an equivalent way of looking at things, we can look at the original code
and askwhich definitioncorresponds to each placeholder use.
The answer is simple - it is always the closest (in terms of nestedness)
enclosing

...

(define w 1)
(define x 3)
(define y 5)

Wiki Markup
(local \[(define w 2)


(define x 4)


(define z 6)\]


(\+ w x y z))

(+ w x y)

HTML
HTML
HTML
HTML

Wiki Markup
(define w 1)


(define x 3)


(define (test x y)


(local \[(define w 2)


(define x 4)


(define z 6)\]


(\+ w x y z))))

(test 8 3)
(test x w)
(test w x)

HTML
HTML
HTML
HTML

Wiki Markup
(define x 1)


(define y 1)


(local \[(define x 2)


(define y x)\]


(\+ x y))


(\+ x y)

HTML
HTML
HTML

Here is an example of mutually recursive functions following the
template for natural numbers.
It is motivated by the observation "a positive number n
is even if n-1 is odd, a positive number n is odd if n-1 is even,
and 0 is even."

HTML

Wiki Markup
(local \[; my-odd?: natnum \--> boolean


(define (my-odd? n)


(cond [(zero? n)
false
     false|(zero? n)     false]
[(positive? n) (my-even? (sub1 n))|(positive? n) (my-even? (sub1 n))]))

; my-even?: natnum --> boolean
(define (my-even? n)
(cond (zero? n) true
(positive? n) (my-odd? (sub1 n))))]

...

HTML

(define x 1)
(define y 2)

Wiki Markup
(define (f x)


(local \[(define (g x) (\+ x y))


(define y 100)\]


(g (g x))))

Wiki Markup
(local \[(define x 30)


(define y 31)


(define (g x) (\* x y))\]


(g 20))

(g 20)
(f 20)

HTML
HTML
HTML
HTML

...

As a reminder, we've discussedfilter.
Starting from several examples using specific predicates,
we noticed a great deal of similarity.
By abstracting away that similarity into a function parameter,
we obtained the following definition:

Wiki Markup
; filter : (X \->boolean) [X] \-> [X] ; Purpose: Returns a list like the one given, except with those       ; elements not passing the given predicate test removed.       (define (filter keep? l)          (cond [(empty? l) empty|(empty? l) empty] \[(cons? l)  (cond [(keep? (first l))                              (cons (first l) (filter keep? (restl)))
else(filter keep?
|(keep? (first l))                              (cons (first l) (filter keep? (restl)))]
))
 [else(filter keep? (restl))|else(filter keep? (restl))])\]))

As an alternative, we could note that the above definition repeats
the code
(filter keep? ...As an alternative, we could note that the above definition repeats
the code
(filter keep? …)
.
I.e.,keep?
is an invariant argument.
We could choose to avoid that, as follows:

Wiki Markup
; filter : (X \->boolean) [X] \-> [X] ; Returns a list like the one given, except with
those ; elements not passing the given predicate test removed. (define (filter keep? l) (local [(define (filter-helper l) (cond (empty? l) empty [(cons? l) (cond (keep? (first l)) (cons (first l) (filter-helper (restl))) else(filter-helper (restl)))]))] (filter-helper
 those      ; elements not passing the given predicate test removed.      (define (filter keep? l)         (local            \[(define (filter-helper l)                (cond [(empty? l) empty|(empty? l) empty] \[(cons? l)  (cond [(keep? (first l))                                    (cons (first l) (filter-helper (restl)))|(keep? (first l))                                    (cons (first l) (filter-helper (restl)))] [else(filter-helper (restl))|else(filter-helper (restl))])\]))\]            (filter-helper l)))

HTML
HTML

filterexercises

HTML

...

(map f (list x<sub>1</sub> ... x<sub>n</sub>)) = (list (f x<sub>1</sub>) ... (f x<sub>n</sub>))

HTML
HTML

...

(foldr f base (list x<sub>1</sub> x<sub>2</sub> ... x<sub>n</sub>)) = (f x<sub>1</sub> (f x<sub>2</sub> ... (f x<sub>n</sub> base)))

Many functions we've written fit this pattern, although
this might not be obvious at first.

...

(andmap f (list x<sub>1</sub> ... x<sub>n</sub>)) = (and (f x<sub>1</sub>) ... (f x<sub>n</sub>)) (ormap f (list x<sub>1</sub> ... x<sub>n</sub>)) = (or (f x<sub>1</sub>) ... (f x<sub>n</sub>)) (build-list n f) = (list (f 0) ... (f (sub1 n)))

The following is a quick summary of the abstract functions mentioned
in this lab:

HTML
HTML

filter
-
selects some elements from a list

...

map
-
applies a function to each list element

HTML
HTML

andmap
/ormap
-
applies a function to each list element and combines the resulting booleans

...

:
(list <VAR>n</VAR>-(<VAR>i</VAR>-1) ... <VAR>n</VAR>-1 <VAR>n</VAR>)More concretely, e.g.,
(nums-upto-help 5 0) ⇒ empty (nums-upto-help 5 2) ⇒ (list 4 5) (nums-upto-help 5 5) ⇒ (list 1 2 3 4 5) (nums-upto-help 6 5) ⇒ (list 2 3 4 5 6) (nums-upto-help 7 5) ⇒ (list 3 4 5 6 7)

...

Defineandmap, which computes
whether all elements in a list of booleans are true:
(andmap f (list x<sub>1</sub> ... x<sub>n</sub>)) = (and (f x<sub>1</sub>) ... (f x<sub>n</sub>))First, define it recursively following the list template, then
define it using
foldr
andmap
,
then using onlyfoldr
.

...

(foldl f base (list x<sub>1</sub> x<sub>2</sub> ... x<sub>n</sub>)) = (f x<sub>n</sub> ... (f x<sub>2</sub> (f x<sub>1</sub> base))...)

HTML
HTML

foldlexercises

HTML

...