[comp.lang.scheme] semantics of DEFINE

Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) (05/01/89)

In article <19890425161147.8.DEATH@MICKEY-MOUSE.LCS.MIT.EDU>, death@ZERMATT
(Mark A. Sheldon) writes:
>Allowing DEFINEs everywhere gives us a weird sort of dynamic scoping.
>Restricting DEFINEs to beginnings of blocks allows us to think of a block
>of internal DEFINEs as a LETREC (though CALL/CC may expose implementations
>that don't implement these blocks as a LETREC).  If Scheme is a statically
>scoped language, then this sort of DEFINE is anathema.  If Scheme is to
>support dynamic scoping, then I think FLUID-LET is cleaner because I don't
>have to think about environment mutation.

A while ago I posted the suggestion that non-top-level DEFINEs do the same
thing as top-level DEFINEs, ie, side effect the top level.  This allows
top-level definitions to scope over lexically bound variables, which cannot be
done in any other way (as of now a single procedure can scope over variables,
but such variables cannot be shared by procedures); having non-top-level
DEFINEs side effect the local lexical environment is the same as LETREC
(perhaps nested) and thus doesn't add any functionality.  This interpretation
is the one adopted by the current version of T (although it's not an explicit
decision on the part of the T designers) and I believe is the interpretation
used by most LISP dialects.  The ability to have global procedures scope over
variables reduces the number of unneeded global variables, allows hiding of
internal representations, and (almost definitely) adds alot to the efficiency
of accessing these variables.

Most of the responses that I got said either like "well, Abelson and Sussman
used the 'local' interpretation, so we really should stick to it" or "well,
local non-top-level DEFINEs add fewer parentheses than nesting LETRECs."  Does
anyone have other (theoretical or functional) reasons for this decision??


Bruce Krulwich

 

mkatz@SESAME.STANFORD.EDU (Morris Katz) (05/01/89)

   Date: 30 Apr 89 20:39:25 GMT
   From: Krulwich-Bruce@yale-zoo.arpa  (Bruce Krulwich)

   In article <19890425161147.8.DEATH@MICKEY-MOUSE.LCS.MIT.EDU>, death@ZERMATT
   (Mark A. Sheldon) writes:
   >Allowing DEFINEs everywhere gives us a weird sort of dynamic scoping.
   >Restricting DEFINEs to beginnings of blocks allows us to think of a block
   >of internal DEFINEs as a LETREC (though CALL/CC may expose implementations
   >that don't implement these blocks as a LETREC).  If Scheme is a statically
   >scoped language, then this sort of DEFINE is anathema.  If Scheme is to
   >support dynamic scoping, then I think FLUID-LET is cleaner because I don't
   >have to think about environment mutation.

   A while ago I posted the suggestion that non-top-level DEFINEs do the same
   thing as top-level DEFINEs, ie, side effect the top level.  This allows
   top-level definitions to scope over lexically bound variables, which cannot be
   done in any other way (as of now a single procedure can scope over variables,
   but such variables cannot be shared by procedures); having non-top-level
   DEFINEs side effect the local lexical environment is the same as LETREC
   (perhaps nested) and thus doesn't add any functionality.  This interpretation
   is the one adopted by the current version of T (although it's not an explicit
   decision on the part of the T designers) and I believe is the interpretation
   used by most LISP dialects.  The ability to have global procedures scope over
   variables reduces the number of unneeded global variables, allows hiding of
   internal representations, and (almost definitely) adds alot to the efficiency
   of accessing these variables.

   Most of the responses that I got said either like "well, Abelson and Sussman
   used the 'local' interpretation, so we really should stick to it" or "well,
   local non-top-level DEFINEs add fewer parentheses than nesting LETRECs."  Does
   anyone have other (theoretical or functional) reasons for this decision??


   Bruce Krulwich



Some systems may not have the concept of A top level environment, so this
proposal restricts Scheme in an important way that should be recognized.  If
one has a system that has first-class environments, then a top level
environment may not exist or may be a dynamic, rather than a static, property
of a piece of executing code.  I would far prefer to see local defined removed
from Scheme than have them given the proposed semantics.
					Morry Katz
					katz@polya.stanford.edu

alms@spt.entity.COM (andrew lm shalit) (05/02/89)

   Date: 30 Apr 89 20:39:25 GMT
   From: Krulwich-Bruce@yale-zoo.arpa  (Bruce Krulwich)

   In article <19890425161147.8.DEATH@MICKEY-MOUSE.LCS.MIT.EDU>, death@ZERMATT
   (Mark A. Sheldon) writes:

   . . .
   A while ago I posted the suggestion that non-top-level DEFINEs do
   the same thing as top-level DEFINEs, ie, side effect the top level.
   . . .
   Most of the responses that I got said either like "well, Abelson
   and Sussman used the 'local' interpretation, so we really should
   stick to it" or "well, local non-top-level DEFINEs add fewer
   parentheses than nesting LETRECs."  Does anyone have other
   (theoretical or functional) reasons for this decision??

How about a general aversion to the notion of "top-level environment"?  When
you introduce first-class environments, and programming tools for using
them, the notion of "top-level" starts to change.  Just how it changes
depends on how the environments and programming tools are designed.

Do you have a problem with the following, aside from the general aversion
to SET! ?

(define frob nil)

(let ((x (mumble1))
      (y (mumble2)))
  (dset! frob (lambda (z)
               (list x y z))))

Ram-Ashwin@cs.yale.edu (Ashwin Ram) (05/02/89)

In article <8905011321.AA03861@spt.entity.com>, alms@spt.entity.COM (andrew lm shalit) writes:
>    Date: 30 Apr 89 20:39:25 GMT
>    From: Krulwich-Bruce@yale-zoo.arpa  (Bruce Krulwich)
> 
>    A while ago I posted the suggestion that non-top-level DEFINEs do
>    the same thing as top-level DEFINEs, ie, side effect the top level.
>    . . .
>    Most of the responses that I got said either like "well, Abelson
>    and Sussman used the 'local' interpretation, so we really should
>    stick to it" or "well, local non-top-level DEFINEs add fewer
>    parentheses than nesting LETRECs."  Does anyone have other
>    (theoretical or functional) reasons for this decision??
> 
> How about a general aversion to the notion of "top-level environment"?  When
> you introduce first-class environments, and programming tools for using
> them, the notion of "top-level" starts to change.  Just how it changes
> depends on how the environments and programming tools are designed.

This is a good argument against DEFINE in general, not against DEFINEs within
LETs in particular.  A top-level DEFINE always assumes that you want to
side-effect the "top-level environment".  What you're really saying is that
DEFINE should take an extra argument, which would explicitly specify the
environment in which the definition should take place.

T does provide such a function, called *DEFINE.  DEFINE is merely a
convenient syntax for doing a *DEFINE in the environment that the startup
REPL works in, called USER-ENV.  The REPL-ENV can be changed as desired.

To get back to the original point, it seems perfectly reasonable to allow
*DEFINEs to be nested within LETs, which would create a definition in the
environment (which is explicitly specified as an argument to the *DEFINE).
The definition is evaluated (and therefore closed) within the lexical
environment of the LET, as any other form would be.

Given that DEFINE is merely a convenient syntax for *DEFINE in the REPL-ENV,
it seems consistent to let a DEFINE with a LET be a convenient syntax for a
*DEFINE within that LET with the REPL-ENV explicitly specified as the
environment for the definition.

-- Ashwin.

Pavel.pa@XEROX.COM (05/04/89)

Too many people are referring to DEFINE as a form that ``side-effects the
top-level environment'' for me to keep out of the fray.  In the current
(unreleased) draft of the Scheme specification, R^(3.95)RS, the following
definitions appear (my wording):

-- A program is a mixed sequence of definitions and expressions.
	
-- The meaning of a program P is the same that that of the following
expression:
	((lambda (I*) P') <undefined> ...)
where I* is the set of variables defined in P (i.e., appearing as the CADR
of a DEFINE form), P' is the sequence of expressions obtained by replacing
each definition in P with the corresponding assignment, and <undefined> is
an expression producing some useless value.

More informally, to execute a program, you wrap it in a big LET binding all
of the defined variables to useless values, change the DEFINEs to SET!s,
and evaluate that expression.

Note, please: no mutation of any environment takes place.

I believe that too many people base their understanding of the semantics of
Scheme on a read-eval-print loop model or on the low-level details of
particular (or perhaps all) implementations.  It seems to me irrelevant
that I might use side-effects to resolve the separate compilation (or just
separate loading) of files of code with the semantics given above.  The
semantics of DEFINE, and therefore the most accurate way to conceptualize
its meaning, has no mention of mutation.

Of course, this little diatribe has no direct bearing on the meaning of
internal DEFINEs.  Personally, I'd rather they had the same meaning (as
given above) as top-level ones.  The meaning in terms of LETREC has always
struck me as gratuitously incompatible, and frequently inconvenient as
well.  If you're going to use the same name, you should give it the same
semantics...

	Pavel

biep@cs.vu.nl (J A Biep Durieux) (05/08/89)

In article <890503-103409-9762@Xerox> Pavel.pa@XEROX.COM writes:

>-- A program is a mixed sequence of definitions and expressions.
>	
>-- The meaning of a program P is the same as that of the following expression:
>		    ((lambda  (I*)  P')  <undefined>  ...)
>where I* is the set of variables defined in P (i.e., appearing as the CADR
>of a DEFINE form), P' is the sequence of expressions obtained by replacing
>each definition in P with the corresponding assignment, and <undefined> is
>an expression producing some useless value.

Then why not actually do this?

-- The scheme top-level environment has each variable bound to a unique
   location.  Many of these locations will be assigned the value #\undefined.

-- The user can assign other values to variable locations using "set!".
   A "define" on top level will be an error, since the variable is
   already bound on that level.

-- Allow the syntax "(set! (first cell) (car cell))" to mean the analogue
   of the comparable "define" syntax
-- 
						Biep.  (biep@cs.vu.nl via mcvax)
	Who am I to doubt the existence of God?   I am
	  only a simple man,  I already have trouble
	enough doubting the existence of my neighbour!

Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) (05/08/89)

In article <890503-103409-9762@Xerox>, Pavel.pa@XEROX writes:
>Too many people are referring to DEFINE as a form that ``side-effects the
>top-level environment'' for me to keep out of the fray.  In the current
>(unreleased) draft of the Scheme specification, R^(3.95)RS, the following
>definitions appear (my wording):
>
>-- A program is a mixed sequence of definitions and expressions.
>	
>-- The meaning of a program P is the same that that of the following
>expression:
>	((lambda (I*) P') <undefined> ...)
>where I* is the set of variables defined in P (i.e., appearing as the CADR
>of a DEFINE form), P' is the sequence of expressions obtained by replacing
>each definition in P with the corresponding assignment, and <undefined> is
>an expression producing some useless value.
>
>More informally, to execute a program, you wrap it in a big LET binding all
>of the defined variables to useless values, change the DEFINEs to SET!s,
>and evaluate that expression.

OK, the above makes sense for "top-level" DEFINE forms.  Before recasting
my comments from before into the terminology used above, let me define two
catagories of DEFINE forms that are not handled under the above
specification:

        (1) non-top-level static definitions: definitions that are made at
            load/compile/etc time (ie, are static) but are not top-level.
            An example of this is a DEFINE form inside a "top-level" LET 
            form.
        (2) dynamic definitions: DEFINE forms that are executed during the
            execution of another procedure.  An example of this is a DEFINE
            form in the body of another DEFINE form.

My claim is that both of these cases fits cleanly into the specification
given above (by Pavel).  In each case the symbol being DEFINEd would be
bound in the global binding countour (shown above as a LAMBDA, essentially
a LET) and would be SET! at the point where they were to be DEFINEd.  The
new specifications (using the terminology from above) would be:

        A program is a sequence of expressions
        The meaning of a program P is the same as that of the expression:
                ((lambda (I*) P') <undefined> ...)
        where I* is the set of variables defined in P (ie, apearing as the 
        CADR of a DEFINE form anywhere in the tree coresponding to P), P'
        is the sequence of expressions obtained by replacing all appearences
        of the symbol DEFINE [perhaps only those where the variable DEFINE 
        isn't rebound] with teh symbol SET!, and <undefined> is an 
        expression producing some useless value.

The next question is why I think the specifications should be extended to
allow this.  My answers are:

        (1) It adds expressive power to the language.
        (2) Other proposed specifications for non-top-level DEFINEs do
            not add expressive power to the language.
        (3) It is a direct and consistant extension of the semantics being
            proposed (according to Pavel).


Bruce Krulwich

 

Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) (05/09/89)

In article <2454@ski.cs.vu.nl>, biep@cs (J A Biep Durieux) writes:
>In article <890503-103409-9762@Xerox> Pavel.pa@XEROX.COM writes:
>
>>-- A program is a mixed sequence of definitions and expressions.
>>	
>>--The meaning of a program P is the same as that of the expression:
>>		    ((lambda  (I*)  P')  <undefined>  ...)
...
>Then why not actually do this?
>
>-- The scheme top-level environment has each variable bound to a unique
>   location.  Many of these locations will be assigned the value 
>   #\undefined.
>
>-- The user can assign other values to variable locations using "set!".
>   A "define" on top level will be an error, since the variable is
>   already bound on that level.

First, the system has to know what symbols to bind in the global LET
contour.  It would be consistant to have DEFINE always specify that a
symbol be included in this binding.

Secondly, having internal DEFINEs do local definitions is even more
redundant, since it is 100% translatable into a LETREC while DEFINE is
needed to specify what variables should be bound.


Bruce Krulwich

 

Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) (05/09/89)

In article <59918@yale-celray.yale.UUCP>, I wrote:
>In article <2454@ski.cs.vu.nl>, biep@cs (J A Biep Durieux) writes:
>>In article <890503-103409-9762@Xerox> Pavel.pa@XEROX.COM writes:
>>
>>>-- A program is a mixed sequence of definitions and expressions.
>>>	
>>>--The meaning of a program P is the same as that of the expression:
>>>		    ((lambda  (I*)  P')  <undefined>  ...)
>...
>>Then why not actually do this?
>>
>>-- The scheme top-level environment has each variable bound to a unique
>>   location.  Many of these locations will be assigned the value 
>>   #\undefined.
>>
>>-- The user can assign other values to variable locations using "set!".
>>   A "define" on top level will be an error, since the variable is
>>   already bound on that level.
>
>First, the system has to know what symbols to bind in the global LET
>contour.  It would be consistant to have DEFINE always specify that a
>symbol be included in this binding.
>
>Secondly, having internal DEFINEs do local definitions is even more
>redundant, since it is 100% translatable into a LETREC while DEFINE is
>needed to specify what variables should be bound.

Gee that last paragraph reads like gibberish.  What I meant was:

  Secondly, having internal DEFINEs do local definitions is even more 
  reduntant since this is 100% translatable into LETREC.  On the other 
  hand, top-level DEFINEs are not 100% translatable since some specification
  is needed of which variables should be in the top-level contour.


Bruce 

 

jar@ZOHAR.AI.MIT.EDU (Jonathan Rees) (05/27/89)

   Date: 30 Apr 89 20:39:25 GMT
   From: Krulwich-Bruce@yale-zoo.arpa  (Bruce Krulwich)

   A while ago I posted the suggestion that non-top-level DEFINEs do
   the same thing as top-level DEFINEs, ie, side effect the top level.
   ... This interpretation is the one adopted by the current version
   of T (although it's not an explicit decision on the part of the T
   designers) and I believe is the interpretation used by most LISP
   dialects.  ...

   Most of the responses that I got said either like "well, Abelson
   and Sussman used the 'local' interpretation, so we really should
   stick to it" or "well, local non-top-level DEFINEs add fewer
   parentheses than nesting LETRECs."  Does anyone have other
   (theoretical or functional) reasons for this decision??

It *was* an explicit decision on the part of the designers, made in
1981.  It was an attempt to have something similar to the MIT Scheme
define but without coupling it to the syntax or semantics of lambda.
We never properly implemented the feature (LOCALE, for those of you
who have seen the T manual) that would have made it coherent, however.
Personally, I now would like to see T changed either to implement R3RS
define or to allow defines only at "top level" (given a suitable
non-global definition of "top level").

I would prefer to see the desired functionality achieved not by a
mechanism like T's but by either (a) a new construct implemented as a
macro or (b) some kind of module system.  I think a number of people
are working on this design problem now.

aarons@syma.sussex.ac.uk (Aaron Sloman) (05/28/89)

jar@ZOHAR.AI.MIT.EDU (Jonathan Rees) writes:

>    From: Krulwich-Bruce@yale-zoo.arpa  (Bruce Krulwich)
>
>    A while ago I posted the suggestion that non-top-level DEFINEs do
>    the same thing as top-level DEFINEs, ie, side effect the top level.
>    ... This interpretation is the one adopted by the current version
>    of T (although it's not an explicit decision on the part of the T
>    designers) and I believe is the interpretation used by most LISP
>    dialects.  ...
>
>    Most of the responses that I got said either like "well, Abelson
>    and Sussman used the 'local' interpretation, so we really should
>    stick to it" or "well, local non-top-level DEFINEs add fewer
>    parentheses than nesting LETRECs."  Does anyone have other
>    (theoretical or functional) reasons for this decision??
>
> It *was* an explicit decision on the part of the designers, made in
> 1981.  It was an attempt to have something similar to the MIT Scheme
> define but without coupling it to the syntax or semantics of lambda.
> We never properly implemented the feature (LOCALE, for those of you
> who have seen the T manual) that would have made it coherent, however.
> Personally, I now would like to see T changed either to implement R3RS
> define or to allow defines only at "top level" (given a suitable
> non-global definition of "top level").
>

In Pop-11 you can use define locally and it is frequently and very
effectively used for two main purposes, and less importantly for
a third:

(a) Temporarily alter the error handler, standard character
output consumer, interrupt handler, or other procedures that define
the current environment, need to be changed in a particular
procedure, and need to be re-set when that procedure is exitted
whether normally or abnormally (e.g. via exitto, or by temporarily
suspending a lightweight process using that procedure - in the
latter case the temporary value is re-set if the procedure is
resumed.) Typical example, redefining -interrupt locally-:

  define foo(...,....);
    lvars oldinterrupt=interrupt;   ;;; save previous value in local var.

    define interrupt();
      pr('Message about being in foo');
      popready();     ;;; interactive break
      oldinterrupt(); ;;; if it exits normally do previous interrupt
    enddefine;

  ...body of foo...

  enddefine

The interrupt procedure (whatever its current value) is called when
the user hits the interrupt key, or after the error handler has
printed its message, or if some procedure explicitly calls it.

The use described in (a) depends on the procedure name being a
dynamically scoped identifier.


(b) Define a local procedure that is required ONLY within the
nesting procedure. Sometimes this can be done by having a procedure
defined at top level with either a unique name, or via  file-local
lexically scoped name, or in a section (Pop-11 sections are a bit
like Packages in Common Lisp, but can be nested). But the local
NESTED procedure definition is most useful when it needs to access
one of the lexically scoped locals of the enclosing procedure. E.g.

    define foo(x, y, z);
        lvars x, y, z;

        define baz(w);
            lvars w;
            if     w == x then ....
            elseif w == y then ....
            elseif w == z then ...
            ....
        enddefine;

        ...body of foo may either call baz or hand it as an argument
        ... to some other procedure or else may return baz as a new
        ... lexical closure

    enddefine;

(Some of these cases can be handled slightly more efficiently, and
slightly more messily using 'partial application', in Pop-11).

My suspicion is that people who don't appreciate the usefulness of
such nested procedure definitions must be people who have not been
using a language that allows these constructs. Here at Sussex there
was a gradual conversion among programmers using Pop-11, especially
after we introduced lexical scoping as an option.

(c) If you simply want to change the global value of a procedure
identifier you can do things like:

    define foo ....;

       define foo_interrupt;
        ....
       enddefine;

        foo_interrupt -> interrupt;     ;;; sets the value outside foo.
    enddefine;

or to ensure that it is set in all current contexts

    set_global_valof(foo_interrupt, "interrupt");

                  --------------------------------

I would say that a lisp-like language that doesn't allow nested
procedure definitions with these capabilities was seriously
impoverished. One can of course achieve similar effects by other
means, but they are bound to be more clumsy and also by not using
the syntactic nesting you risk hiding an important relationship,
and thereby confusing people responsible for maintaining code they
did not write.

The impoverishment in case (a) is reduced if your language does not
provide a "process" mechanism, which not all Lisps do.

Aaron Sloman,
School of Cognitive and Computing Sciences,
Univ of Sussex, Brighton, BN1 9QN, England
    INTERNET: aarons%uk.ac.sussex.cogs@nsfnet-relay.ac.uk
              aarons%uk.ac.sussex.cogs%nsfnet-relay.ac.uk@relay.cs.net
    JANET     aarons@cogs.sussex.ac.uk
    BITNET:   aarons%uk.ac.sussex.cogs@uk.ac
        or    aarons%uk.ac.sussex.cogs%ukacrl.bitnet@cunyvm.cuny.edu

    UUCP:     ...mcvax!ukc!cogs!aarons
            or aarons@cogs.uucp

shaff@Sesame.Stanford.EDU (Mike Shaff) (05/30/89)

ciao,

In article <1030@syma.sussex.ac.uk>, aarons@syma (Aaron Sloman) writes:
>jar@ZOHAR.AI.MIT.EDU (Jonathan Rees) writes:
>>
>> It *was* an explicit decision on the part of the designers, made in
>> 1981.  It was an attempt to have something similar to the MIT Scheme
>> define but without coupling it to the syntax or semantics of lambda.
>> We never properly implemented the feature (LOCALE, for those of you
>> who have seen the T manual) that would have made it coherent, however.
>> Personally, I now would like to see T changed either to implement R3RS
>> define or to allow defines only at "top level" (given a suitable
>> non-global definition of "top level").
>>
>
>In Pop-11 you can use define locally and it is frequently and very
>effectively used for two main purposes, and less importantly for
>a third:
>
>(a) Temporarily alter the error handler, standard character
>output consumer, interrupt handler, or other procedures that define
>the current environment, need to be changed in a particular
>procedure, and need to be re-set when that procedure is exitted
>whether normally or abnormally (e.g. via exitto, or by temporarily
>suspending a lightweight process using that procedure - in the
>latter case the temporary value is re-set if the procedure is
>resumed.) Typical example, redefining -interrupt locally-:
>


Though Scheme has no standard for speaking about interrupt handlers and
presuming that the code that was handling the interrupt dispatch did so using
the current environment (an admittedly complex issue with interrupts), I see no
reason why the standard LET & LETREC could not supply the functionality you are
seeking.  As I understand your comment you wish to have local definitions, as
Scheme believes in first class functions, functions can be introduced any place
that a Scheme object can be introduced.  What is at issue here is the meaning
of the define "command."


>  define foo(...,....);
>    lvars oldinterrupt=interrupt;   ;;; save previous value in local var.
>
>    define interrupt();
>      pr('Message about being in foo');
>      popready();     ;;; interactive break
>      oldinterrupt(); ;;; if it exits normally do previous interrupt
>    enddefine;
>
>  ...body of foo...
>
>  enddefine


(define foo
  (lambda (...)
    (let ((interrupt
	   (lambda ()
	     (newline) (display Message about being in foo)
	     (break)			;!Not standard! push a break loop
	     (interrupt))))		;This reference to interrupt refers to
					;the binding of interrupt outside this
					;environment
      body of foo)))

Please note that I do not agree that this is the best way to shadow an
interrupt handler, however I am showing how to transliterate the above code
segment. 


>
>(b) Define a local procedure that is required ONLY within the
>nesting procedure.


Again, the functionality of LET & LETREC allow this. (e.g.,

;; BLORF alpha beta     [FUNCTION]
;;
;; PURPOSE: Stupid example of how to get notification in a given context.
;;

(define blorf
 (lambda (alpha beta)
  (let ((cons                              ;Define a new cons to give notice
         (lambda (obj-1 obj-2)
          (newline) (display "Cons was called from blorf")
          (cons obj-1 obj-2))))            ;Refer to the cons outside
   (if (eq? alpha beta)
    (cons alpha beta)
    (vector alpha beta)))))

 
>
>My suspicion is that people who don't appreciate the usefulness of
>such nested procedure definitions must be people who have not been
>using a language that allows these constructs. Here at Sussex there
>was a gradual conversion among programmers using Pop-11, especially
>after we introduced lexical scoping as an option.
>


Having the ability to nest functions is, of course, a wonderful thing, but I do
not believe that anyone in the Scheme community contests that.  The questions
related to first class incremental environments, WELL there you will get
discussion.


>(c) If you simply want to change the global value of a procedure
>identifier you can do things like:
>
>    define foo ....;
>
>       define foo_interrupt;
>        ....
>       enddefine;
>
>        foo_interrupt -> interrupt;     ;;; sets the value outside foo.
>    enddefine;


(define foo
 (lambda (...)
  (let ((foo-interrupt
         (lambda ()
          ...)))

   (set! interrupt foo-interrupt)        ;Sets the value outside foo.

   ...)))

>
>or to ensure that it is set in all current contexts
>
>    set_global_valof(foo_interrupt, "interrupt");
>


I have no idea what this would mean in Scheme, so...


>
>I would say that a lisp-like language that doesn't allow nested
>procedure definitions with these capabilities was seriously
>impoverished. One can of course achieve similar effects by other
>means, but they are bound to be more clumsy and also by not using
>the syntactic nesting you risk hiding an important relationship,
>and thereby confusing people responsible for maintaining code they
>did not write.
>


I could not agree more, however Scheme *DOES* allow nested procedure
definitions, that properly capture the environment in which it was created,
passed around, etc.

(peace chance)

  mas
--