Re: pTk for guile?

Paul R. Wilson (wilson@cs.utexas.edu)
Wed, 9 Apr 1997 18:39:42 -0500

>From guile-owner@cygnus.com Wed Apr 9 17:50:27 1997
>
>Right, and this would be easy if Scheme had complete lexical scoping.
>Consider:
>
>(let ((foo (lambda () ...)))
> (... stuff ...
> (foo 'bar)))
>
>Now how can foo be changed before bar without an explicit and obvious
>"let" or "set!"? This function can be called 100 times and foo will
>always have the same value, no matter what happens outside of it. Isn't
>it the exception to lexical scoping at the top level environment that
>allows the value of "cons" to change between one execution of a function
>and another?

Scheme does have complete lexical scoping. Jim's right that the
problem is one of assignment, not of scoping.

Conceptually, all of the top level bindings behave as though they
were bindings in a big letrec.

If you compile a whole Scheme program using a batch compiler, you
can take advantage of this. The compiler can treat the whole thing
as a big letrec, notice which variables are assigned to in any
of the code, and do optimizations knowing their values will
be constant. (like inlining procedures.)

The hitch with this is that it doesn't work if you can evaluate
arbitrary expressions in the top-level environment, as you can
from the read-eval print loop. The compiler can't tell that you'll
never type in an expression that will side-effect a top-level
binding, rendering its optimizations incorrect.

This is why modules are good. If you can "seal" a module (promise
never to evaluate new expressions in it), you can find the bindings
that are never made visible to other modules and never assigned to
within the module. Those can easily be determined to have constant
values, which can be inlined.

You should actually be able to do this within the language, automating
it with a few handy macros. Your "module" macro just translates
the enclosed definitions in a big letrec, with some extra cruft
to ensure that the initializations are done in the right order.
(You also need a little extra cruft to notice which bindings are
exported, and treat them specially.)

Then a good Scheme compiler will be able to notice which bindings
are never assigned to from any code within their scope, and do lots of
inlining and/or serious interprocedural analysis.

Unfortunately, this doesn't get you separate compilation. You need
support from the underlying system to be able to actually compile
modules separately, and link them together. Most good Scheme systems
have this support, but it's not standardized.