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

macros, &REST and REMF

27 views
Skip to first unread message

Sam Steingold

unread,
Nov 29, 2002, 9:11:19 PM11/29/02
to
Is this the right idiom:

(defmacro with-foo ((&key foo) &body body)
`(... ,foo ... ,@body))

(defmacro with-foo-bar ((&rest opts &key bar &allow-other-keys) &body body)
(remf opts :bar)
`(with-foo (,@opts)
... ,bar ... ,@body))

I.e., I want all options for WITH-FOO to be available in WITH-FOO-BAR.

thanks.

--
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
Isn't "Microsoft Works" an advertisement lie?

Barry Margolin

unread,
Nov 30, 2002, 1:15:03 AM11/30/02
to
In article <m365ufh...@loiso.podval.org>,

Sam Steingold <s...@gnu.org> wrote:
>Is this the right idiom:
>
>(defmacro with-foo ((&key foo) &body body)
> `(... ,foo ... ,@body))
>
>(defmacro with-foo-bar ((&rest opts &key bar &allow-other-keys) &body body)
> (remf opts :bar)
> `(with-foo (,@opts)
> ... ,bar ... ,@body))
>
>I.e., I want all options for WITH-FOO to be available in WITH-FOO-BAR.

It's a pretty common style. Another possibility is:

(defmacro with-foo-bar (...)
`(with-foo (:allow-other-keys t ,@opts)
... ,bar ... ,@body))

However, this prevents WITH-FOO from doing any keyword validation of the
remaining arguments.

--
Barry Margolin, bar...@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Rob Warnock

unread,
Nov 30, 2002, 3:58:40 AM11/30/02
to
Sam Steingold <s...@gnu.org> wrote:
+---------------

| Is this the right idiom:
| (defmacro with-foo ((&key foo) &body body)
| `(... ,foo ... ,@body))
|
| (defmacro with-foo-bar ((&rest opts &key bar &allow-other-keys) &body body)
| (remf opts :bar)
| `(with-foo (,@opts)
| ... ,bar ... ,@body))
+---------------

Side question for the group: What are the rules for a &REST arg
in macros? If they're the same as functions, then could you possibly
get in trouble with Sam's idiom due to REMF destructively modifying
the "opts" list? That is, does one really need to do this instead?

(defmacro with-foo-bar ((&rest opts &key bar &allow-other-keys) &body body)

(let ((mutable-opts (copy-list opts)))
(remf mutable-opts :bar)
`(with-foo (,@mutable-opts)
... ,bar ... ,@body)))


-Rob

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

Erik Naggum

unread,
Nov 30, 2002, 2:09:25 PM11/30/02
to
* Rob Warnock

| Side question for the group: What are the rules for a &REST arg in
| macros? If they're the same as functions, then could you possibly get in
| trouble with Sam's idiom due to REMF destructively modifying the "opts"
| list?

I believe that is the actual question, presented in his usual turbid way.
The "idiom" is a recipe for disaster for macros and functions precisely
because it may clobber a list that it does not own, but it is, of course,
not a question about `remf´. The issue of ownership of the argument list,
which has been answered many times over and which does not change just
because of some particular operator, should be pretty clear: Do not mutate
the argument list. This is close to a principle, and the answer does not
change depending on the operator used to transmogrify it, obviously.

(defun sans (plist &rest keys)
(let ((sans ()))
(loop
(let ((tail (nth-value 2 (get-properties plist keys))))
;; this is how it ends
(unless tail
(return (nreconc sans plist)))
;; copy all the unmatched keys
(loop until (eq plist tail) do
(push (pop plist) sans)
(push (pop plist) sans))
;; skip the matched key
(setq plist (cddr plist))))))

I wrote this some time ago when I wanted to find a use for `nreconc´.

It can be called as `(apply <function> (sans <arglist> :foo))´. Its main
features are that it conses minimally and is more efficient than making
multiple passes over the same list for more than one key. (It is assumed
that `get-properties´ is fast.)

--
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.

0 new messages