![]() |
![]() |
|
home—info—lectures—exams—hws—archive
We have already seen that Scheme has a let statement; it can actually be implemented in terms of a function-call:
(let {[a 2] [b 4]} (+ 3 a b)) = ((lambda (a b) (+ 3 a b)) 2 4) = (+ 3 2 4) = 9 |
(define a 1) (let {[a 2] [b (sqr a)]} (+ 3 a b)) |
Scheme does happen to provide let*. let* can be implemented by expanding it into nested lets.1 Here's an example:
(define a 1) (let* {[a 2] [b (+ sqr a)]} (+ 3 a b)) = ; Rewrite as nested lets: (let {[a 2]} (let {[b (sqr a)]} (+ 3 a b))) = ; Which, following the already-known rules, becomes: ((lambda (a) (let {[b (sqr a)]} (+ 3 a b))) 2) = ; Note how there's no confusion about using the global a=1. (let {[b (sqr 2)]} (+ 3 2 b)) = (let {[b 4]} (+ 3 2 b)) = ; Now, follow regular ol' rules for evaluation a function-application: ((lambda (b) (+ 3 2 b)) 4) = (+ 3 2 4) = 9 |
Finally, what about a version where the scope includes the current let-branch? For variables, this is never desirable ('variable used before initialized'), but it is necessary for recursive functions:
(define (insert-sort lon) (letrec {[insert (lambda (n nums) (cond [(empty? nums) (list n)] [(cons? nums) (if (< n (first nums)) (cons n nums) (cons (first nums) (insert n (rest nums))))]))]} (foldl insert empty lon))) ; Another example, using mutual recursion: (letrec {[a 2] [even? (lambda (n) (or (zero? n) (odd? (sub1 n))))] [odd? (lambda (n) (not (even? n)))]} (even? a)) |
There are also wacky ways to explore exactly how Java's scoping works (it's different for fields vs. locals). See also: a silly main.
Implementing fields. Note that each (pair of) functions has its own closure.
Dynamic scope: (Lisp; Perl.)
class Foo() { int x = 3; void foo() { ++x; // If dynamically scoped: refers to 'most recently declared' x print(x); // in a *dynamic* sense! } void haha() { foo(); } void lala() { int x = 9; foo(); } void gaga() { int x = 5; foo(); } } class Hoo() { int x; Foo.foo(); } |
Other ways of controlling access:
1 (Therefore, let* isn't really a primitive scoping mechanism; it's just convenient syntactic sugar. In the same way that let itself can be thought of as syntactic sugar for passing to a parameter.) ↩
home—info—lectures—exams—hws—archive
©2009, Ian Barland, Radford University Last modified 2009.Apr.20 (Mon) |
Please mail any suggestions (incl. typos, broken links) to ibarland ![]() |
![]() |