[alexandria-devel] DESTRUCTURE-CLAUSES - alexandria_destruct#9CF676.diff (1/1)
Tobias C Rittweiler
tcr at freebits.de
Thu Apr 26 09:15:25 UTC 2012
In article
<CADow0CpTq8ns8xx065Uk7P92-w98b6njBkzK4f9qUffh3iaqpw at mail.gmail.com>,
Nikodemus Siivola <nikodemus at random-state.net> wrote:
> On 25 April 2012 16:47, Tobias C Rittweiler <tcr at freebits.de> wrote:
>
> > I was pleased to discover that DESTRUCTURING-CASE made it into
> > Alexandria meanwhile. Very nice! This allows me to share the
> > little gem that I'm attaching with this posting. It's a handy
> > macro to make writing macros like DEFPACKAGE, DEFGENERIC of
> > DEFREADTABLE easy like a breeze.
>
> Nice!
>
> Unless I misread this, duplicate clauses cause the earlier one to be
> discarded? Signaling an error instead might be better,
Yes, that is true. I also regularly use the following macro in
macro definitions:
;;; This is a macro for sake of nicer indentation of the format control.
(defmacro assert-no-duplicates (list (&key test key) &body
(format-control . format-args))
"If LIST contains duplicates, an error is signaled. FORMAT-CONTROL,
and FORMAT-ARGS are passed to ERROR along an enumeration of the
duplicated items."
`(%assert-no-duplicates ,list ,test ,key ,format-control (list
, at format-args)))
(defun %assert-no-duplicates (list test key format-control format-args)
(let* ((test (if test (ensure-function test) #'eql))
(no-dups (remove-duplicates list :test test :key key)))
(unless (= (length list) (length no-dups))
(error "~@<~? ~:_Duplicates are:~:_ ~:I~{~S~^, ~:_~}~:>"
format-control format-args
(dolist (x no-dups list)
(setq list (remove (if key (funcall key x) x) list
:count 1 :test test :key key)))))))
E.g.
(defmacro defpackage (name &body clauses)
(assert-no-duplicates clauses (:key #'car)
"Found duplicates in the clauses passed to ~S."
`(defpackage ,name))
(destructure-clauses clauses
((:uses &rest uses)
...)
(expand-defpackage uses ...)))
Do you want me to provide that as a patch, too?
> though a fairly
> common pattern might also be served by special casing clauses of the
> form
>
> (:keyword &append stuff)
>
> or something like that, which would cause duplicate clauses to have
> their contents merged.
I don't know. It invents unprecedented syntax for a not really common
case. And the manual way doesn't seem that bad:
(destructure-clauses clauses
((:foo &rest xs1)
(:bar &rest xs2)
...)
(let ((xs (append xs1 xs2)))
...))
> Or maybe that should be factored into a separate function MERGE-ALIST,
> for preprocessing the clauses?
>
> function MERGE-ALIST keys alist &optional (merge #'append)
>
> ...or something along those lines?
That one seems useful on its own. How comes you think the merging
of clause parameters is anything but a rare occasion anyhow?
T
T
More information about the alexandria-devel
mailing list