[plt-scheme] Scopes and closures

From: Todd O'Bryan (toddobryan at gmail.com)
Date: Mon Jan 19 08:37:44 EST 2009

Hey all!

As a fun project (read that as "frustrating time sink that's driving
me crazy"), I've been implementing a version of Scheme in Python. Like
all good naive implementers of programming languages, I managed to
implement dynamic scope accidentally and so I'm now trying to fix
that. I have a few clarifying questions to ask so that I can make sure
I really understand what I'm doing.

1. Is the following program in HtDP Beginning Student sufficient to
show the difference between dynamic and static scope?
(define n 5)

(define (f x)
  (+ x n))

(define (g n)
  (f 3))
If I'm reasoning correctly, with static scope, f is saved with its
closure, so n is forever bound to 5 and g applied to anything will
always return 8. In dynamic scope, n would get its value from the
argument passed into g. So,

(g 7) --> 8 = static scoping
(g 7) --> 10 = dynamic scoping

Is that right? If not, is there a Beginning Student program that would
differentiate between dynamic and static scope?

2. In creating a closure, it's really only necessary to save values
that the function uses, rather than the whole context. I did notice a
difference in the way that's implemented (maybe). In the HtDP
languages, a program like
(define (f x)
  (+ x n))
throws an error when you click run, saying that n is not defined. In
R5RS, you don't get an error until you try to use f. On the other
hand, it's not just checking in order, because if I add (define n 5)
*after* the definition of f, it works fine in both the HtDP languages
and R5RS. So, my question is, do you read in all the functions and
then create the closures, or do you keep a list of undefined names as
you're going through and then report errors if any are left by the
time you get to the end of the definitions, or is there something more
subtle going on? I guess I'm asking where the source code that handles
this is defined so I can take a look at it.

3. How is type checking usually integrated with this? Do most
implementations check type safety as they're figuring out closures, do
it as an add-on step after, or even--I guess this is possible--check
the type safety before trying to create the closure?

Thanks for any insight,

Posted on the users mailing list.