Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

what is &aux used for?

2,571 views
Skip to first unread message

Tamas K Papp

unread,
Sep 29, 2009, 4:34:24 AM9/29/09
to
What is the point of &aux? Section 3.4.1.5 in the HS says it is
equivalent to a let* inside the body. So is it a redundant feature in
the standard, or does it have any uses which justify it being there?
If so, an example would be appreciated.

Thanks,

Tamas

Rainer Joswig

unread,
Sep 29, 2009, 5:20:53 AM9/29/09
to
In article <7idv4gF...@mid.individual.net>,

&aux is a feature of Lisps that Common Lisp inherited from older
Lisps to define auxiliary variables.
Remember, Common Lisp was designed to be compatible with
other Lisps in the MacLisp tradition.

&aux lets you define auxiliary variables.

(defun foo (x &aux (sx (sin x)) (i 0))
...)


instead of

(defun (x)
(let* ((sx (sin x))
(i 0))
...)


It allows you to get rid of a level of LET indentation in the body.
The aux variables are listed at the top.
The aux variables can refer to variable values
of other variables in the lambda list on the left.

For those who are not used to fancy parameter lists with
&rest, &key, &aux, &optional, etc. it looks unusual. For example
Scheme lambda lists are by default primitive.

The only criteria to use it or not is: does it help you
to layout your code better? If yes, use it. I doubt
it will be removed from Common Lisp anytime soon.

Other than that it is not that widely used anymore.
Older code bases (like Maxima) tend to use it.

--
http://lispm.dyndns.org/

Pascal J. Bourguignon

unread,
Sep 29, 2009, 5:49:37 AM9/29/09
to

I heard it could be useful in macro writing...
That said, a command such as:
find /usr/local/share/lisp/ -type f -name \*.lisp -exec grep -ni '&aux' {} /dev/null \;
prints a surprizingly high number of lines...


--
__Pascal Bourguignon__

Rob Warnock

unread,
Sep 29, 2009, 6:07:06 AM9/29/09
to
Tamas K Papp <tkp...@gmail.com> wrote:
+---------------
+---------------

There was a thread [Subject: idiomatic Lisp style] back in February
in which Mark Wooding pointed out a really hacky use that's *not*
trivially rewritable as a LET*, namely, an auto-initialized arg in
a DEFSTRUCT BOA constructor lambda list, e.g.:

> (defvar *box-count* 0)

*BOX-COUNT*
> (defstruct (box
(:constructor box (value &aux (count (incf *box-count*)))))
value count)

BOX
> (box 123)

#S(BOX :VALUE 123 :COUNT 1)
> (box 456)

#S(BOX :VALUE 456 :COUNT 2)
> (box-value *)

456
> (setf (box-value **) 789)

789
> ***

#S(BOX :VALUE 789 :COUNT 2)
> (box-count *)

2
>


-Rob

-----
Rob Warnock <rp...@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

Vassil Nikolov

unread,
Sep 29, 2009, 6:14:21 AM9/29/09
to

On 29 Sep 2009 08:34:24 GMT, Tamas K Papp <tkp...@gmail.com> said:

> What is the point of &aux?

In my opinion, one point is that it allows a very easy "promotion"
of a local variable to a formal parameter, e.g. from

(defun foo (s &aux (start 0) (end (length s))) ...)

to

(defun foo (s &key (start 0) (end (length s))) ...)

(and similarly from &AUX to &OPTIONAL), or possibly vice versa,
which may be useful while the programmer is deciding what exactly an
interface should be.

---Vassil.


--
"Even when the muse is posting on Usenet, Alexander Sergeevich?"

Joshua Taylor

unread,
Sep 29, 2009, 8:06:19 AM9/29/09
to

Similarly, Google Code Search gives some hits too (though some of them
are from lisp implementations that need to recognize &aux in
lambda-lists...). See

http://www.google.com/codesearch?q=lang%3Alisp+%26aux

A search in some my projects show a few different kinds of uses. One is
binding a single single variable that (and so avoiding a level of
indentation, but also /any/ binding forms in the function body at all).
E.g., along the lines of:

(defun prompt-for-... (... &aux (*read-eval* nil))
(display-prompt ...))

Another use that I'm fond of, though I'm sure others may have different
preferences, is for accumulator values. It's idiomatic, for instance,
to collect lists by PUSHing objects into a list l and then returning
(NREVERSE l).

(defun listify-collection (collection &aux (items '()))
(docollection (x collection (nreverse items))
(push (... x) items)))

Sometimes I use temporary hash-tables, for instance to implement an easy
visitedp within a graph traversal, and I'll make the hash table with
&aux, and the recursive traversal functions with labels. Something like
this (untested):

(defun dfmap (fn nodes children &aux (visited (make-hash-table)))
(labels ((visit (node)
(unless (gethash node visited)
(setf (gethash node visited) t)
(dolist (child (funcall children node) (funcall fn node))
(visit child)))))
(map nil #'visit nodes)))


Finally, I'm a fan of ...-designators, be they string-designators,
list-designators, or so on, and try to write functions that can operate
on them when appropriate. I'll often use an &aux binding to do the
conversion to the designated type (by calling STRING on string
designators, to-list on list designators (i.e., (IF (LISTP X) X (LIST
X))), and so on). I find this useful for functions dealing with string
designator, and for macros dealing with list-designators (e.g.,
CASE-like macros where the standard forms accept list designators).

//JT

Pascal Costanza

unread,
Sep 29, 2009, 8:51:44 AM9/29/09
to

There is one place where &aux is indispensable, and that's for defining
non-trivial initializations of struct slots. For example:

(defstruct
(wrapped-array (:constructor make-wrapped-array
(length &aux (array (make-array length)))))
array)

However, I also tend to use &aux more and more for variables that are
initialized with values that can be directly derived from function
arguments. I know this is a fuzzy idea, but I think it tends to be clear
with concrete examples, like:

(defun foo (array &aux (length (length array)))
...)

(defun bar (object &aux (class (class-of object)))
...)

For more complex computations, I tend to use 'real' local variables
introduced with let and let*, for clarity.


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/

Thomas A. Russ

unread,
Sep 29, 2009, 12:01:27 PM9/29/09
to
Rainer Joswig <jos...@lisp.de> writes:

> In article <7idv4gF...@mid.individual.net>,


>
> &aux is a feature of Lisps that Common Lisp inherited from older
> Lisps to define auxiliary variables.
> Remember, Common Lisp was designed to be compatible with
> other Lisps in the MacLisp tradition.
>
> &aux lets you define auxiliary variables.

...


>
> It allows you to get rid of a level of LET indentation in the body.
> The aux variables are listed at the top.
> The aux variables can refer to variable values
> of other variables in the lambda list on the left.

I wonder when LET* appeared in relation to &aux.

Certainly if you had a Lisp with LET, but not LET*, the case for using
&aux would be particularly compelling, since you would then eliminate
multiple levels of LET nesting.

That said, I've often seen it in Lisp Machine code, particularly when
there was some very short function definition (~2 lines) and putting the
variable binding in to the lambda list saved the vertical space for the
LET block.

That said, I'm not a particular fan of it, since I think it clutters
what I think of as the function's interface description.

--
Thomas A. Russ, USC/Information Sciences Institute

Rainer Joswig

unread,
Sep 29, 2009, 2:51:10 PM9/29/09
to
In article <ymifxa5...@panacea.isi.edu>,

t...@sevak.isi.edu (Thomas A. Russ) wrote:

> Rainer Joswig <jos...@lisp.de> writes:
>
> > In article <7idv4gF...@mid.individual.net>,
> >
> > &aux is a feature of Lisps that Common Lisp inherited from older
> > Lisps to define auxiliary variables.
> > Remember, Common Lisp was designed to be compatible with
> > other Lisps in the MacLisp tradition.
> >
> > &aux lets you define auxiliary variables.
> ...
> >
> > It allows you to get rid of a level of LET indentation in the body.
> > The aux variables are listed at the top.
> > The aux variables can refer to variable values
> > of other variables in the lambda list on the left.
>
> I wonder when LET* appeared in relation to &aux.
>
> Certainly if you had a Lisp with LET, but not LET*, the case for using
> &aux would be particularly compelling, since you would then eliminate
> multiple levels of LET nesting.
>
> That said, I've often seen it in Lisp Machine code, particularly when
> there was some very short function definition (~2 lines) and putting the
> variable binding in to the lambda list saved the vertical space for the
> LET block.

I was just searching through my Lisp folder and found it in 1/8 of all
Lisp files.

Software that makes 'heavy' use of &aux is for example

* building problem solvers, Forbus/de Kleer
* AIMA
* FOCL
* Joshua
* ESS
* OMAR
* PAIL
* QSIM
* CL-HTTP
* McCLIM
* CLIM 2
* Genera
* Maxima

>
> That said, I'm not a particular fan of it, since I think it clutters
> what I think of as the function's interface description.

I used to think that, too.

One might think it is kind of an interface description,
where parts of the interface variables are not passed in, but
are computed. Kind of an internal interface to the body code.

--
http://lispm.dyndns.org/

Slobodan Blazeski

unread,
Sep 30, 2009, 1:13:53 PM9/30/09
to
On Sep 29, 10:34 am, Tamas K Papp <tkp...@gmail.com> wrote:
> What is the point of &aux?  Section 3.4.1.5 in the HS says it is
> equivalent to a let* inside the body.  So is it a redundant feature in
> the standard, or does it have any uses which justify it being there?
&aux redundant no way, its a great feature for golfing.

Bobi
http://www.linkedin.com/in/slobodanblazeski

Willem Broekema

unread,
Oct 1, 2009, 5:50:25 AM10/1/09
to
On 29 sep, 10:34, Tamas K Papp <tkp...@gmail.com> wrote:
> What is the point of &aux?

For macros that introduce lexical binding, besides saving an
indentation step it can also be an elegant solution for the problem of
bound declarations ending up in the wrong place.

For example this macro introduces the variable %magic:

(defmacro def-foo (func-name params &body body)
`(defun ,func-name ,params
(let ((%magic (frub ,(car params))))
,@body)))

But the declaration ends up in a wrong location:

(macroexpand-1 '(def-foo f (x y)
(declare (ignorable y))
(zut %magic x)))
=>
(defun f (x y)
(let ((%magic (frub x)))
(declare (ignorable y))
(zut %magic x)))

A simple fix is to use &aux:

(defmacro def-foo (func-name params &body body)
`(defun ,func-name (,@params &aux (%magic (frub ,(car params))))
,@body))

which gives the right expansion:

(defun f (x y &aux (%magic (frub x)))
(declare (ignorable y))
(zut %magic x))

- Willem

Pascal Costanza

unread,
Oct 1, 2009, 6:08:48 AM10/1/09
to

Nice!

Timofei Shatrov

unread,
Oct 1, 2009, 6:28:28 AM10/1/09
to
On 29 Sep 2009 08:34:24 GMT, Tamas K Papp <tkp...@gmail.com> tried to confuse
everyone with this message:

For example you're writing a web application and have a function that processes
a form. It doesn't have the parameters passed directly, and you use something
like (post-parameter "string") to retrieve post parameters during the function
execution. But it's clearer (to me, at least) to think of them as the arguments
to the function. So you write

(defun process-form (&aux (username (post-parameter "username"))
(subject (post-parameter "subject"))
(text-field (post-parameter "textfield")))
;;...
)

IMO it's much clearer than an equivalent let* form (which would normally be used
to introduce local variables that don't depend on the external state).

--
|Don't believe this - you're not worthless ,gr---------.ru
|It's us against millions and we can't take them all... | ue il |
|But we can take them on! | @ma |
| (A Wilhelm Scream - The Rip) |______________|

Alex Mizrahi

unread,
Oct 1, 2009, 6:38:15 AM10/1/09
to
TKP> What is the point of &aux? Section 3.4.1.5 in the HS says it is
TKP> equivalent to a let* inside the body. So is it a redundant feature in
TKP> the standard, or does it have any uses which justify it being there?

LET is also redundant, you can write (let ((a x) (b y)) body)
as ((lambda (a b) body) x y).
And you can write LET* as nested LETs (or LAMBDA's).


Raymond Toy

unread,
Oct 1, 2009, 8:35:56 AM10/1/09
to
>>>>> "Alex" == Alex Mizrahi <udod...@users.sourceforge.net> writes:

TKP> What is the point of &aux? Section 3.4.1.5 in the HS says it is
TKP> equivalent to a let* inside the body. So is it a redundant feature in
TKP> the standard, or does it have any uses which justify it being there?

Alex> LET is also redundant, you can write (let ((a x) (b y)) body)
Alex> as ((lambda (a b) body) x y).

Almost. I don't think you can't change (let ((&optional x)) body) to
((lambda (&optional) body) x). The former is valid, but the latter
means something different.

Ray

Thomas F. Burdick

unread,
Oct 1, 2009, 9:33:17 AM10/1/09
to
On Oct 1, 2:35 pm, Raymond Toy <raymond....@stericsson.com> wrote:

But you can change it to ((lambda (optional &aux (&optional optional))
body) x)

Thomas A. Russ

unread,
Oct 1, 2009, 2:52:52 PM10/1/09
to
Willem Broekema <meta...@gmail.com> writes:

> On 29 sep, 10:34, Tamas K Papp <tkp...@gmail.com> wrote:
> > What is the point of &aux?
>
> For macros that introduce lexical binding, besides saving an
> indentation step it can also be an elegant solution for the problem of
> bound declarations ending up in the wrong place.

...


> A simple fix is to use &aux:
>
> (defmacro def-foo (func-name params &body body)
> `(defun ,func-name (,@params &aux (%magic (frub ,(car params))))
> ,@body))
>
> which gives the right expansion:
>
> (defun f (x y &aux (%magic (frub x)))
> (declare (ignorable y))
> (zut %magic x))

Cool use!

Tim Bradshaw

unread,
Oct 1, 2009, 4:08:15 PM10/1/09
to
On 2009-09-29 09:34:24 +0100, Tamas K Papp <tkp...@gmail.com> said:

> What is the point of &aux?

Compatibility.

Kaz Kylheku

unread,
Oct 1, 2009, 5:04:52 PM10/1/09
to
On 2009-09-29, Tamas K Papp <tkp...@gmail.com> wrote:
> What is the point of &aux? Section 3.4.1.5 in the HS says it is
> equivalent to a let* inside the body.

And what's the point of a LET* inside the body? It's equivalent to
a bunch of nested lets (modulo some declaration refactoring).

And what's the point of LET? You can just de-zipper your var-init
pairs and write a LAMBDA.

Etc.

&AUX is nice because you can add extra local variables to a function
without having to introduce an extra binding construct.

It works in other contexts too, like destructuring bind.

(destructuring-bind (a b c &aux (d 4)) (list 1 2 3)
...)

More convenient than

(destructuring-bind (a b c) (list 1 2 3)
(let ((d 4))
...))

> So is it a redundant feature in
> the standard

Yes! And it's not the only one:

- () and NIL
- (a . (b . c)) and (a b c)
- CL: and COMMON-LISP:
- 'FORM and (QUOTE FORM)
- abc, Abc, ABC, AbC, aBC, ...
- |1234| and |1|234 and 1\234 ...
- #| ... |# as well as ; ...
- (ZEROP X) as well as (= 0 X)
- (CONS A B) in spite of (LIST* A B) which is more general.
- (AND X Y Z ...) as well as (NOT (OR (NOT X) (NOT Y) (NOT Z) ...)

Etc.

Tim Toady!

Vassil Nikolov

unread,
Oct 1, 2009, 11:40:26 PM10/1/09
to

On Thu, 1 Oct 2009 06:33:17 -0700 (PDT), "Thomas F. Burdick" <tbur...@gmail.com> said:

> On Oct 1, 2:35�pm, Raymond Toy <raymond....@stericsson.com> wrote:

>> ...


>> Almost. �I don't think you can't change (let ((&optional x)) body) to
>> ((lambda (&optional) body) x). �The former is valid, but the latter
>> means something different.

> But you can change it to ((lambda (optional &aux (&optional optional))
> body) x)

Or

(defmacro let~ ((&rest bindings) &body body)
((lambda (variables values)
`((lambda (&optional ,@(mapcar #'list variables)) ,@body)
,@values))
(mapcar #'(lambda (b) (if (listp b) (first b) b)) bindings)
(mapcar #'(lambda (b) (if (listp b) (second b) nil)) bindings)))

so that

* (let~ ((&optional 'foo)) (list '&optional &optional))
(&OPTIONAL FOO)
* (macroexpand +)
((LAMBDA (&OPTIONAL (&OPTIONAL)) (LIST '&OPTIONAL &OPTIONAL)) 'FOO)
T

though that starts to sound a bit like one of the names from _Catch 22_...

And it is, of course, quite unnecessary, because of

(defmacro let~ ((&rest bindings) &body body)
`((lambda (&optional ,@(mapcar #'(lambda (b) (if (listp b) b (list b)))
bindings))
,@body)))

Vassil Nikolov

unread,
Oct 1, 2009, 11:46:00 PM10/1/09
to

On Thu, 1 Oct 2009 02:50:25 -0700 (PDT), Willem Broekema <meta...@gmail.com> said:
> ...

> (defmacro def-foo (func-name params &body body)
> `(defun ,func-name (,@params &aux (%magic (frub ,(car params))))
> ,@body))

That is smart; a bit of nit-picking:

(defmacro def-foo (func-name params &body body)

`(defun ,func-name (,@params ,@(if (member '&aux params) '() '(&aux)) (%magic (frub ,(car params))))
,@body))

---Vassil.

0 new messages