[comp.lang.lisp] DEFVAR is forever

alms@cambridge.apple.com (Andrew L. M. Shalit) (02/01/90)

In article <1652@skye.ed.ac.uk> jeff@aiai.ed.ac.uk (Jeff Dalton) writes:

   However, nothing says an implementation can't provide some way to
   turn off a SPECIAL proclamation (which is how DEFVAR makes the
   variable special).  There just isn't a standard way to do it.

Turning off a special proclamation would involve going through all the
compiled functions in the world which reference the variable, and
changing them to treat the variable as lexical.  Some implementations
might be able to backpatch the functions, but others would probably
need to recompile them.  Needless to say, this could be a *very*
expensive operation.  (Don't forget to include the time needed
to walk all the functions in the world looking for the references.)

  -andrew

barmar@think.com (Barry Margolin) (02/09/90)

In article <ALMS.90Jan31142823@brazil.cambridge.apple.com> alms@cambridge.apple.com (Andrew L. M. Shalit) writes:
>Turning off a special proclamation would involve going through all the
>compiled functions in the world which reference the variable, and
>changing them to treat the variable as lexical.

This is not necessary.  Just as DEFVAR doesn't find previous references to
the variable and change them from lexical to special, there's no need for
UNDEFVAR to go back and change them from special to lexical.  There's
precedent for this: (proclaim '(notinline <function-name>)) doesn't
de-inline previous invocations of the function.

Of course, since we're describing an implementation-dependent extension, we
can't really say for sure how it would behave.  If an implementation wanted
to provide the semantics you describe, and wanted to make it efficient, it
could keep back pointers.  However, I'm not sure why you'd want those
semantics.  Consider the following code:

(defvar *foobar*)

(defun fun1 (arg)
  (let ((*foobar* (* arg arg)))
    (fun2))

(defun fun2 ()
  (print *foobar*))

(undefvar *foobar*)

The point of the DEFVAR/UNDEFVAR is to make *FOOBAR* special only in the
functions FUN1 and FUN2; they're equivalent to wrapping all the functions
in a (locally (declare (special *foobar*)) ...).

In general, changing declarations should not affect previously-defined
functions.
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

jeff@aiai.ed.ac.uk (Jeff Dalton) (02/11/90)

In article <ALMS.90Jan31142823@brazil.cambridge.apple.com> alms@cambridge.apple.com (Andrew L. M. Shalit) writes:
>In article <1652@skye.ed.ac.uk> jeff@aiai.ed.ac.uk (Jeff Dalton) writes:

>   However, nothing says an implementation can't provide some way to
>   turn off a SPECIAL proclamation (which is how DEFVAR makes the
>   variable special).  There just isn't a standard way to do it.

>Turning off a special proclamation would involve going through all the
>compiled functions in the world which reference the variable, and
>changing them to treat the variable as lexical.

I'd call that "undoing the effects of the DEFVAR".  In any case, I
didn't intend it to be a necessary part of "turn off".  The variable
could be made nonspecial [ie, no longer proclaimed special] without
undoing all the effects of it having once been special.

A fairly similar case would be that of redefining a macro as a
function.  Many implementations let you do that but don't try to
make the world be as if the macro had never been defined.

>Some implementations might be able to backpatch the functions, but
>others would probably need to recompile them.

Here too it's useful to think of the macro case.  A number of
implementations re-expand macro calls each time they're evaluated by
the interpreter.  (Or they cache expansions and re-expand only if the
macro has been redefined.)  Likewise, they re-determine whether or not
a variable is special each time the interpreter evaluates a binding
form.  So most of the effects are undone, in effect, just by the way
the interpreter works.  It's only when we turn to compiled code that
things like backpatching and recompilation become necessary.  Most
implementations (as far as I know) don't automatically undo the
effects of canceled special proclamations, or of macros redefined as
function, in compiled code.

-- Jeff