[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

common lisp- &environment objects

    Date: Sun, 9 Jun 1985  23:17 EDT
    From: "Scott E. Fahlman" <Fahlman@CMU-CS-C.ARPA>

	    One false move here and we have not Lisp but Conniver.  How about
	    requiring "dynamic" extent for environment objects, and no more?  Will
	    that take care of the needs for macro-expansion, steppers, and so on?
	    True, you could imagine cute ways of using environments that outlive
	    their invocations, but I REALLY don't want to pay for those cute uses
	    with inefficiency or severe constraints on the implementor.  If anyone
	    wants to implement Conniver in Common Lisp, I can supply the old Maclisp
	    code, but let's not drag down Common Lisp itself.

	Moon very carefully solved this problem in Symbolics' implementation of
	Common Lisp by having an &ENVIRONMENT keyword to defmacro and making
	sure all possible expanders of macros took an optional environment
	argument, to which they can pass to MACROEXPAND(-1).  This isn't cute;
	it is functional.  It isn't inefficient and it doesn't pose any
	constraints on the implementor, unless I misunderstand what "the
	implementor" is suposed to mean.

    I don't understand what you are saying here.  What does this have to do
    with the extent of environment objects?  What, exactly, are you arguing

I'm arguing that CLtL says much too little about environments.  It does
not say how to get your hands on one, but specifies them as optional
arguments to functions, for example EVALHOOK, APPLYHOOK, MACROEXPAND(-1)
(and in our implementation EVAL).  Dynamic extent isn't good enough; how
can you do upward funargs?  This is far from cute:
	(defun adder (val)
	  #'(lambda (x) (+ x val)))
it is instead at the heart of lexical scoping.

    As I said in an immediate follow-up to the above message, you only get a
    lot of additional expense if you actually let users do all of the
    "obvious" things with an immortal environment object, such as going to
    the tags 
Tags have dynamic extent.  Going with tags outside their dynamic extent
should generate errors.
    and diddling the lexical variables.
What good is lexical scoping if you can't diddle lexical variables?
    I really don't care if
    environment objects have indefinite or dynamic extent, as long as these
    expensive kinds of uses are clearly forbidden once you exit the dynamic
    extent, but the politics of this group are such that we must be very
    careful about introducing features that, if taken to their logical
    conclusion, lead us to somewhere we don't want to go; there are always a
    lot of people who demand that everything be taken to its logical
    conclusion, and damn the expense, so it is sometimes better not to take
    the first step.
CLtL'84, on page 39 pretty clearly gives the scope and extent of just
about everything.  Maybe you are concerned that I want the users to
diddle with the environment itself?  Not at all.  The structure of the
environment is peculiar to the implementation.  I am, perhaps
incorrectly, assuming that creating a lexical closure captures the
current environment.

    I do note that the original query suggested that Symbolics was
    stack-allocating environment objects, and other implementations might
    want to do similarly tense things in order to make the interpreter
    reasonably cons-free.  That suggests to me that it would be a good idea
    to allow environment objects to have dynamic extent only, unless someone
    can explain why this is unworkable or can demonstrate some important
    thing that cannot be done if we take this position.  I am always
    nervous about disappearing objects, such as the disappearing &rest args
    in Zetalisp (not legal in Common Lisp), but in the case of environment
    arguments we might choose to go with a dangerous but efficient solution.
I'll repeat the classic lexical scoping example:
	(defun adder (val)
	  #'(lambda (x) (+ x val)))
Environments must have indefinite extent (at least the environment of
non-special variables and local functions (FLET, LABELS)).  The way this
works is that the environment has a slot which is called ENV-EVACUATION
which is the heap version created as necessary.  Therefore, internal
interpreter functions (e.g., the definition of the FUNCTION special
form) explicitly evacuate the environment since it is being stored in
permanent storage.