[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Macros -> declarations
Date: Fri, 17 May 1985 23:50 EDT
From: "Scott E. Fahlman" <Fahlman@CMU-CS-C.ARPA>
Now there's an idea: flush local SPECIAL declarations altogether,
keeping only global SPECIAL proclamations. I'll have to think about
this awhile to see if I really believe that we can do without these
declarations, but it is certainly a very attractive suggestion at first
glance. Can anyone think of a really important use for such
declarations?
I can provide a few from recent experience with Macsyma. I'm not sure they'll
convince you 100%, but hopefully they'll at least make you stop and think.
It largely depends on whether you consider the goal is to produce a language
that's clean and shiny or one that cares about things like compatibility with
the past where possible, etc. I think these goals conflict pretty badly. With
my language designer's hat on, I'd reject almost all of these arguments out of
hand. But since CL was designed by people prone to wear their politician's hats
a lot of the time, I'm of the impression that things like "compatibility with
the past" and such are likely to carry more weight, so here goes...
* Sometimes a function will need to be compiled "out of place" (eg,
before the relevant DEFVAR is loaded). In such cases, the problem
may go away if you move the definition containing the spurious
reference to another file (which is processed after the DEFVAR),
but the SPECIAL declaration may linger.
* In any large system which is being converted incrementally from some other
Lisp dialect (eg, old Maclisp or a relative, Interlisp, ...), it may be
desirable to incrementally convert the semantics of variables used by
functions. Using local SPECIAL declarations, you can gradually whittle away
the region in which certain specials are used. If you force global SPECIAL
declarations, you undermine the ability to make such transitions incrementally.
* Although Macsyma is being converted for Common Lisp, it may continue to run
in other dialects of Lisp as well. As such, FLET and friends may not be
available in those dialects and a number of situations may arise where
local SPECIAL declarations provide a way of achieving compatibility with
those otherwise-not-cooperating dialects.
* There are numerous examples of special variables being used as
communication between three or four definitions. We've been working on
converting:
(DECLARE (SPECIAL X))
(DEFUN FOO () ... refers to special X ...)
(DEFUN BAR () ... refers to special X ...)
(DECLARE (UNSPECIAL X))
into
(DEFUN FOO () (DECLARE (SPECIAL X)) ... refers to special X ...)
(DEFUN BAR () (DECLARE (SPECIAL X)) ... refers to special X ...)
This a couple of advantages worth noting.
* Common Lisp has no UNSPECIAL declaration (that I could find).
If the special is a common name like X, we need to not have every
reference to X compiled SPECIAL. It may be very expensive and
dangerous (ie, in terms of potential for typos, timing errors, etc)
to change all 180 source files for Macsyma to use names that could
reasonably be left SPECIAL all the time. (At some point we may
consider this, but...)
* It makes it explicit when you look at a particular definition
just how the communication is being done (since mostly these variables
don't have *...* around them.
* It is a -very- common problem that we will modify a definition
and just put that definition in a patch file, only to find it compiles
differently out of context because the appropriate SPECIAL declarations
were not present. Having the SPECIAL declarations in the definition
means they will move with the definition into the patch file. (This
problem would be "solved" by making SPECIAL declarations global and
outlawing UNSPECIAL, but would mean I'd have to rename an awful lot of
variables, which I mentioned above is a bit scary...)
----Fahlman:
I don't understand Moon's comment that local SPECIAL declarations have
mostly been used to simulate what FLET does better. Can you elaborate a
bit?
I assume he meant that variables which must be accessed in downward funargs
(eg, to MAPCAR and user-defined friends) no longer have to be passed special.
Likewise, what people used to write as:
(DEFUN IN (OBJ TREE) (DECLARE (SPECIAL OBJ)) (IN1 TREE))
(DEFUN IN1 ()
(DECLARE (SPECIAL OBJ))
(COND ((ATOM TREE) (EQ OBJ TREE))
(T (OR (IN1 (CAR TREE)) (IN1 (CDR TREE))))))
can now be written:
(DEFUN IN (OBJ TREE)
(LABELS ((IN1 (TREE)
(COND ((ATOM TREE) (EQ OBJ TREE))
(T (OR (IN1 (CAR TREE)) (IN1 (CDR TREE)))))))
(IN1 TREE)))
----Fahlman:
As Moon points out, even with this change we would still need PARSE-BODY
for macro writers,
or my &BODY hack. No sense in not providing both, though.
but it would sure make life easier for the interpreter, since the other
declarations can all be ignored unless you're doing tense error-checking.