Page 1 of 1

(eval-when (&any ...))

PostPosted: Thu Mar 21, 2013 9:11 am
by garethw
I noticed that SLIME presents the following prototype for the EVAL-WHEN form:

Code: Select all
(eval-when (&any :compile-toplevel :load-toplevel :execute) &body body)


I was curious about the &any lambda list keyword, which is obviously not a standard keyword. Is this just SLIME being helpful for this particular special form? Or can you write a lambda list in such a way that SLIME presents a similar hint? I have need to write a macro with a number of optional keywords I'd like to support. I know how I could do that - but it certainly wouldn't be hinted like this.

Hope I'm not starting to monopolize this forum with my questions - feel free to ask me to dial down the verbosity.

Re: (eval-when (&any ...))

PostPosted: Fri Mar 22, 2013 2:59 am
by edgar-rft
SLIME uses &any to describe how the arguments can be used, but &any is no legal Common Lisp lambda list marker like &optional or &rest. Here is what happens if I use &any in the lambda list of a function definition (SBCL 1.1.5):

Code: Select all
(defun foo (&any bar baz) nil)
=> STYLE-WARNING: suspicious variable in lambda list: &ANY

SBCL thinks that &any is an ordinary Lisp variable with a strange name.

The reason why &any is used in SLIME is that in th CL Specification the EVAL-WHEN syntax is defined as:

eval-when (situation*) form* => result*

In this definition situation*, form*, and result* all three need extra paragraphs to describe their meaning, while in SLIME it's more important that the syntax description fits into one single line. The details are described in the file "slime/contrib/swank-arglists.lisp" below the ARGLIST defstruct.

- edgar

Re: (eval-when (&any ...))

PostPosted: Fri Mar 22, 2013 6:18 am
by edgar-rft
Some time and some experiments later...

garethw wrote:I have need to write a macro with a number of optional keywords I'd like to support ... it certainly wouldn't be hinted like this.

Reading "slime/contrib/swank-arglists.lisp" it turns out that the &ANY hint is produced by specialized methods of the swank:arglist-dispatch function, so the only way to get your own &ANY hint would be to write your own swank:arglist-dispatch method.

Here is the "eval-when" arglist-dispatch method from "slime/contrib/swank-arglists.lisp":

Code: Select all
(defmethod arglist-dispatch ((operator (eql 'eval-when)) arguments)
  (declare (ignore arguments))
    (let ((eval-when-args '(:compile-toplevel :load-toplevel :execute)))
    (make-arglist
     :required-args (list (make-arglist :any-p t :any-args eval-when-args))
     :rest '#:body :body-p t)))

I think it's too much work to add specialized swank:arglist-dispatch methods for every function or macro, but this is left to your decision... ;)

- edgar

Re: (eval-when (&any ...))

PostPosted: Fri Mar 22, 2013 6:22 am
by garethw
Great info, Edgar. Diving into SLIME source code is probably a little advanced for my modest CL chops. I'll leave that as a future project. :)