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

Macros -> declarations



    Date: Tue, 7 May 1985  10:18 EDT
    From: "Scott E. Fahlman" <Fahlman@CMU-CS-C.ARPA>

	Date: Tue, 7 May 85 08:51 EDT
	From: Bernard S. Greenberg <BSG@STONY-BROOK.SCRC.Symbolics.COM>

	I don't buy this as a counterargument to what KMP said.  Subsitute "DEFUN"
	for "DECLARE" in the above paragraph.    You can only define functions with
	DEFUN -- (generic)Lisp provides no other way.  Yet, we have the whole
	top-level macro mechanism to allow you to define application-language-embedded
	function-definers, calls to whom are expanded at top-level to ultimately
	produce DEFUNs.  DECLARE is the only way to declare things lexically.
	The same arguments apply.

    I guess I didn't make myself clear.  I understand that macros are able
    to provide suitable disguises for anything that takes the form of a list
    to be evaluated, such as DEFUN, and that this is useful in creating
    embedded sublanguages with a LIsp-like syntax.  My point was that we do not
    have anything like macros for disguising "structural" items that are not
    in the form of lists to be evaluated: argument lists, things like
    &optional, T and NIL, certain keywords, declarations, components of
    declarations, doc strings, and so on.  Various parts of the interpreter
    look for such things verbatim, without doing any macro-expansion of
    objects or structures that might turn into the item being sought.

I guess the issue is whether you think of DECLARE as "structural". Consider:

(DEFMACRO FROB (WIDGET)
  (COND ((> MOST-NEGATIVE-FIXNUM something)
	 ...expansion that assumes WIDGET was represented as a fixnum...)
	(T
	 ...expansion that assumes WIDGET was represented as a list...)))

(DEFMACRO DECLARE-WIDGET (&REST NAMES)
  `(DECLARE (TYPE ,(IF (> MOST-NEGATIVE-FIXNUM something) 'FIXNUM 'LIST) ,@NAMES)))

(DEFUN FOO (X)
  (DECLARE-WIDGET X)
  ... (FROB X) ...)

Certainly I need as a minimum the ability to do this. It is not reasonable 
(as you seem to be proposing) that I should have to do:

(DEFMACRO DEFINE-WIDGET-OPERATION (NAME BVL &BODY FORMS)
  `(DEFUN FOO ,BVL
     (DECLARE ...hair to parse &WIDGET keywords in BVL 
	         or DECLARE-WIDGET magic at head of FORMS...)
     ,@FORMS))

since it is not compositional -- ie, if I have a similar DEFINE-GIZMO-OPERATION
macro, I cannot easily define something which frobs both gizmos and widgets.
Hence, I claim the declaration is not structural in the sense that, for example,
a COND clause is.

By the way, Macsyma does this sort of thing with read-conditionals because
languages don't allow it the flexibility to do it any other way. I hope I don't
have to explain to you how and why this offends me.

By the way, Skef's proposal (for "declaration macros") handles this problem, too.
I'm just a little skeptical about a special-purpose declaration macro just
for this context. Certainly it is the minimum potentially acceptable position,
since it at least tries to address the issues I'm raising rather than sweeping
them under the rug. I'm a little afriad that next people will want COND macros
and LAMBDA macros (oops, the LispM has them already) and ... but I might yet be
willing to yield to the suggestion of these declaration macros -- I'm still
thinking about it in light of some of the problems I mentioned in my last message.

    That's good for efficiency, particularly in the presence of MACROLET,
    and gives the human reader of Lisp code at least a few stable landmarks
    to hold on to.  The price is that if you really want to monkey around
    with these structural things in an embedded language, you have to
    transform the whole surrounding form and not just the item itself.  To
    me that seems like a reasonable price for those people who want an
    embedded language that departs from Lisp syntax in such a deep way.  If
    you get rid of parentheses or prefix notation or argument lists, you'll
    have to do a transformation on the whole form anyway; I'm just saying
    that we could reasonably consider declarations to be something basic to
    the syntax of the language, like argument lists, rather than thinking
    of them as a funny kind of body form.  Just because (DECLARE ...) looks
    like any old lisp form, that doesn't mean we have to treat it as one.

I just don't buy this claim that it's an efficiency issue. Moon's recent
messages claims this was done efficiently on the Lisp Machine.
Experience with Scheme likewise suggests this can be done efficiently.
You only have to do it once when the form is first seen by the
interpreter and never again. There's no loss of efficiency there. In
fact (leaving aside the question of macrofied declares for the context
of this sentence), if you are lazily or repeatedly expanding macros,
you're risking having a function change its behavior in midstream on any
expression involving macros, which I'd claim is a violation of the maxim
that interpreted and compiled code should execute the same for legal
expressions.