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

Re: Issue MACRO-FUNCTION-ENVIRONMENT, v1



I'm sorry, I should have caught this sooner. The following two issues were
passed at previous meetings (GET-SETF-METHOD-ENVIRONMENT and
MACRO-FUNCTION-ENVIRONMENT.)

Issue:          GET-SETF-METHOD-ENVIRONMENT
References:     GET-SETF-METHOD (CLtL p 187)
Category:       Change
Edit History:   Version 1 9-Jan-87, Version 1 by Masinter 
                (no version) 7-Apr-87, merged with ENVIRONMENT-ARGUMENTS
                Version 2 29-May-87, extracted again 
                Version 3  5-Jun-87, by Masinter
                Version 4  11-Jun-87, for release
                Version 5  13-Jul-87, by Masinter
                
Problem Description:

If a macro that performs similar processing to SETF uses GET-SETF-METHOD,
and that macro occurs within a MACROLET, the expansion will not see the
MACROLET definition, e.g.,

 (defmacro special-incf ... (get-setf-method ...) ...)

then  

 (macrolet ((test (x) `(car ,x)))
         (special-incf (test z)))

would not "see" the test definition.

Proposal (GET-SETF-METHOD-ENVIRONMENT:ADD-ARG):

Add an optional environment argument to GET-SETF-METHOD and
GET-SETF-METHOD-MULTIPLE-VALUE. If the argument is not supplied, it
defaults to the null lexical environment. NIL can also be passed explicitly
to denote the null lexical environment.

Allow &ENVIRONMENT variable to appear in the lambda-list subform of a
DEFINE-SETF-METHOD form, as with a DEFMACRO.

Note that macros defined with DEFINE-MODIFY-MACRO correctly pass the
environment to GET-SETF-METHOD.

Clarify that, within the scope of a MACROLET, FLET and LABELS, global SETF
definitions of the name defined by the MACROLET, FLET or LABELS do not
apply.  A SETF method applies only when the global function binding of the
name is lexically visible.  All of the built in macros of Common Lisp
(SETF, INCF, DECF, POP, ROTATEF, etc.) which modify location specifications
obey this convention.

Test Case:

;;; This macro is like POP 

(defmacro xpop (place &environment env)
  (multiple-value-bind (dummies vals new setter getter)
                       (get-setf-method place env)
     `(let* (,@(mapcar #'list dummies vals) (,(car new) ,getter))
        (prog1 (car ,(car new))
               (setq ,(car new) (cdr ,(car new)))
               ,setter)))))

(defsetf frob (x) (value) 
    `(setf (car ,x) ,value))

;;; The following will modify (cdr z) and not (car z)
(macrolet ((frob (x) `(cdr ,x)))
     (xpop (frob z)))

;;; The following is an error; an error may be signaled at macro expansion
time

(flet ((frob (x) (cdr x))
     (xpop (frob z)))


Rationale:

This was an omission in the original definition of CLtL.

Current Practice:

Many Common Lisp implementations already have this extension, although some
do not. One implementation has extended GET-SETF-METHOD to take an optional
argument which is incompatible with this use.

Cost to implementors:

Some implementations will have to add this feature, although it is not a
major change.

Cost to users:

This is generally an upward compatible change. In implementations which did
not already take into account the lexical environment for SETF'd forms
might start working differently if the internal implementation of SETF is
changed. The likelihood of this affecting a user's program is very small.

Benefits:

This change improves portability and the ability to use MACROLET, FLET and
LABELS in portable code which might also have SETF forms.

Aesthetics:

SETF methods cannot work correctly within lexically defined function
symbols without this change. This change makes the language more consistent
and correct. 

Discussion:

The cleanup committee generally supports this change.

A number of additional changes for rationally dealing with lexical
environments as first class objects, including a more general set of
accessors and constructors for lexical environments is required for many
language extensions (e.g., a portable version of the proposed Common Lisp
Object System) and should be addressed by a future proposal. For a while,
the cleanup committee attempted to deal with these issues together, but
decided to separate them out into their component parts. This issue is the
simplest.


- - - - - - - - - - - - - - - - - - - - - - - - - -

Issue:         MACRO-FUNCTION-ENVIRONMENT

References:    MACRO-FUNCTION, p. 144
               MACROLET, pp. 113-4
               &ENVIRONMENT, pp. 145-6
               MACROEXPAND and MACROEXPAND-1, pp. 151-2

Category:      ADDITION

Edit history:  Version 1, Pavel, March 21, 1988
		   Version 2, Masinter,  8-Jun-88, (as per cleanup discussion)

Problem description:

The &ENVIRONMENT argument to a macro-expansion function may only be used as
the
second argument to the functions MACROEXPAND and MACROEXPAND-1.  It is
sometimes
more convenient, however, to be able to work directly with the more
primitive
function MACRO-FUNCTION, on which MACROEXPAND and MACROEXPAND-1 are
presumably
based.  However, since MACRO-FUNCTION does not take an environment
argument, it
cannot be used in situations in which that environment must be taken into
account.

Proposal (MACRO-FUNCTION-ENVIRONMENT:YES):

Add an optional second argument to MACRO-FUNCTION, that argument being an
environment that was passed as the &ENVIRONMENT argument to some macro
expansion
function.  If the argument is not given, or the argument is NIL, the null
environment is used.  MACRO-FUNCTION will now consider macro definitions
 from
that environment in preference to ones in the global environment.  It is an
error
to supply the environment argument in a use of MACRO-FUNCTION as a SETF
location
specifier.

Examples:

(macrolet ((foo (&environment env)
              (if (macro-function 'bar env)
                 ''yes
                 ''no)))
   (list (foo)
         (macrolet ((bar () :beep))
            (foo))))

=> (no yes)

(setf (macro-function 'bar env) ...) is an error.

Rationale:

Intuitively, the more primitive operation in macro expansion is
MACRO-FUNCTION,
not MACROEXPAND or MACROEXPAND-1, yet the environment argument can only be
supplied to the latter functions and not to the former one.  By changing
this
state of affairs, the model of macro expansion becomes somewhat simpler.
Also,
more flexible use of the facility is enabled.

Current practice:

Xerox Common Lisp already implements this proposal.  Symbolics Common Lisp,
and Kyoto Common Lisp do not. Lucid Common Lisp did not, but version 3.0
does.

Cost to Implementors:

This is presumably a simple change to make, a small matter of moving the
environment-searching code from MACROEXPAND-1 to MACRO-FUNCTION.

Cost to Users:

The change is upward-compatible and so poses no cost to users.

Cost of non-adoption:

One more (small) semantic wart on the language.

Benefits:

The function that users think of as being more primitive really is.

Aesthetics:

This slightly cleans up the language.

Discussion:

This issue was discussed starting in January 1987, but got tangled in
a web of other related proposals. In its current form, the only objections
have been that some other proposal or committee might otherwise change
macro handling, or that this proposal doesn't fix enough of the problems.