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

Issue: SYMBOL-MACROFLET (Version 1)

    Date: 20 Sep 88 17:53 PDT
    From: masinter.pa@Xerox.COM
    Is this a cleanup issue/proposal or just an interesting discussion?

I thought about it and decided I'd better write it up.
The more I think of it, the more I'm inclined to believe it would
be really useful (and perhaps quite hard to do without).

References:   None
Category:     ADDITION
Edit history: 30-Sep-88, Version 1 by Pitman
Status:	      For Internal Discussion

Problem Description:

  The SYMBOL-MACROLET facility provides access to only one of the two
  Common Lisp namespaces. 

  For example, in the expression (F G), it is possible to bind the
  semantics of G using SYMBOL-MACROLET, but there is no analogous
  facility for binding the semantics of F.
  The ability to have symbol-macros in the functional namespace would
  make the creation of a Flavors compatibility package for CLOS much
  more feasible. In particular, the DEFUN-IN-FLAVOR feature of Flavors
  is not easy to implement efficiently without it.


  Introduce a new macro, SYMBOL-MACROFLET, described as follows:

  SYMBOL-MACROFLET ({(symbol expansion)}*) &BODY forms

   The macro SYMBOL-MACROFLET provides a mechanism for the substitution
   of functional expressions for function names with a lexical scope.

   The SYMBOL argument specifies the symbol with which the form
   specified  by the EXPANSION argument is to be associated.

   Each reference to SYMBOL as a function within the lexical scope of
   SYMBOL-MACROFLET is replaced by EXPANSION (not the result of evaluating

   The result is that obtained by executing the forms specified by the
   body FORMS. 

   The lexical scope of SYMBOL-FMACROLET is the body FORMS; it does not
   include EXPANSION.

   The use of SYMBOL-MACROFLET can be shadowed by FLET or MACROLET. In
   other words, SYMBOL-MACROFLET only substitutes for occurrences of SYMBOL
   that would be in the scope of a lexical function binding of SYMBOL
   (such as that done by FLET or MACROLET) surrounding the body.

Test Case:

  (defun ff (x y) (list x y))

  (defun op (object)
    (symbol-macroflet ((f (lambda (x) (ff object x))))
      (list (f 1) (f 2))))

  is equivalent to 

  (defun op (object)
    (list ((lambda (x) (ff object x)) 1) ((lambda (x) (ff object x)) 2)))


  This satisfies the stated goals.

  In principle, it would seem as if FLET be used. It has equivalent 
  expressional power, but in practice the compiler in most implementations
  expects that local functions declared in FLET and LABELS will actually
  be used in the body. Some implementations even complain when the functions
  are not used.

  To get around the expectation that FLET functions will be used, it may
  be necessary to do 
   (FLET ((F ...)) #'F ...)
  to make sure F gets used, but then some compilers do not optimize that
  idiom -- sometimes just producing unreachable code, sometimes even consing
  a gratuitous closure.

  FLET with INLINE declarations cannot be depended upon portably because
  there is no requirement that every implementation support the INLINE
  declaration in a serious way.

  MACROLET cannot be used because #'symbol would not be possible.

  The only other option is to write a code-walker, but that option has been
  pretty much shot to bits in the analogous argument about SYMBOL-MACROLET.

Current Practice:

  Symbolics Cloe has this primitive internally (called SYMBOL-FMACROLET).
  It has been used successfully to implement support for DEFUN-IN-FLAVOR,
  producing a noticeable improvement in compilation-speed.

Cost to Implementors:

  Once you're dealing with SYMBOL-MACROLET, this is little extra effort.

Cost to Users:

  None. This extension is compatible.

Cost of Non-Adoption:

  A portable compatibility package for Flavors would be difficult to
  provide in a way that was both fully portable and reliably efficient.


  Other applications involving macros that must introduce FLET bindings
  which might not get used might be sped up by converting to this

  Some code could be made faster in implementations which did not
  support the INLINE declaration for FLET'd functions by switching to
  this primitive.


  This extension corrects the asymmetry in functionality introduced with


  Pitman supports this extension.