From: Peter Seibel
Subject: Does anyone worry about out-of-order evaluation of &key parameters to macros?
Date: 
Message-ID: <m3eklk5qxh.fsf@javamonkey.com>
Since there are lot of macros with the basic form:

  (defmacro foo ((arg1 arg2 &key another yet-another) &body body)
    ...)

Now ordinarily when writing macros we usually try to make sure the
arguments are evaluated once and in the order given in the macro call
(unless there's a particular reason not to). However with &key
arguments there's no way to know what order they were passed unless we
throw in an &rest or maybe a &whole parameter. Does anyone actually
bother worry about that for this kind of macro?

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp

From: Timothy Moore
Subject: Re: Does anyone worry about out-of-order evaluation of &key parameters to macros?
Date: 
Message-ID: <wdrbrgonw78.fsf@serveur5.labri.fr>
Peter Seibel <·····@javamonkey.com> writes:

> Since there are lot of macros with the basic form:
> 
>   (defmacro foo ((arg1 arg2 &key another yet-another) &body body)
>     ...)
> 
> Now ordinarily when writing macros we usually try to make sure the
> arguments are evaluated once and in the order given in the macro call
> (unless there's a particular reason not to). However with &key
> arguments there's no way to know what order they were passed unless we
> throw in an &rest or maybe a &whole parameter. Does anyone actually
> bother worry about that for this kind of macro?

Arrgh, yes, this is a pet peeve of mine. One possible solution is to
make the macro a thin wrapper around a function which is passed the
keyword arguments.

Here's another approach I took with one macro in McCLIM. This kind of
thing gives me chills.

Tim

;;; All the monkey business with the lambda form has to do with capturing the
;;; keyword arguments of the macro while preserving the user's evaluation order.

(defmacro filling-output ((stream &rest args &key fill-width break-characters
                                  after-line-break after-line-break-initially)
                          &body body)
  (declare (ignore after-line-break-initially))
  (when (eq stream t)
    (setq stream '*standard-output*))
  (with-gensyms (fill-var break-var after-var initially-var)
    `((lambda (&key ((:fill-width ,fill-var))
               ((:break-characters ,break-var))
               ((:after-line-break ,after-var))
               ((:after-line-break-initially ,initially-var)))
        (declare (ignorable ,fill-var ,break-var ,after-var))
        (let ((,stream (make-instance
                        'filling-stream
                        :stream ,stream
                        ,@(and fill-width `(:fill-width ,fill-var))
                        ,@(and break-characters
                               `(:break-characters ,break-var))
                        ,@(and after-line-break
                               `(:after-line-break ,after-var)))))
          (when ,initially-var
            (write-string ,after-var ,stream))
          ,@body))
      ,@args)))
From: Paul Dietz
Subject: Re: Does anyone worry about out-of-order evaluation of &key parameters  to macros?
Date: 
Message-ID: <41389350.60D0540@motorola.com>
Timothy Moore wrote:
> 
> Peter Seibel <·····@javamonkey.com> writes:
> 
> > Since there are lot of macros with the basic form:
> >
> >   (defmacro foo ((arg1 arg2 &key another yet-another) &body body)
> >     ...)
> >
> > Now ordinarily when writing macros we usually try to make sure the
> > arguments are evaluated once and in the order given in the macro call
> > (unless there's a particular reason not to). However with &key
> > arguments there's no way to know what order they were passed unless we
> > throw in an &rest or maybe a &whole parameter. Does anyone actually
> > bother worry about that for this kind of macro?
> 
> Arrgh, yes, this is a pet peeve of mine. One possible solution is to
> make the macro a thin wrapper around a function which is passed the
> keyword arguments.

Another approach is to write a submacro that doesn't preserve argument
order.  The main macro just introduces temporaries for all the keyword
arguments (you could write a general-purpose function for this) and
wraps that around an invocation of the submacro with the temporaries
in place of the keyword forms.)

	Paul