[alexandria.git] updated branch master: 6ddf676 new: DESTRUCTURING-CASE, -CCASE, and -ECASE
Nikodemus Siivola
nsiivola at common-lisp.net
Thu Sep 23 15:30:55 UTC 2010
The branch master has been updated:
via 6ddf67679735379135dbb85042a65257571fce0b (commit)
via 0c6f41f5cdf5bb33111d3b21c7daae50fc636456 (commit)
from f5df120eff98c753d238a64c2db19c9665bc50c5 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 6ddf67679735379135dbb85042a65257571fce0b
Author: Nikodemus Siivola <nikodemus at random-state.net>
Date: Thu Sep 23 18:22:28 2010 +0300
new: DESTRUCTURING-CASE, -CCASE, and -ECASE
I've been wondering about adding these for a fair while
now, but they _are_ nice when writing eg. certain kinds
of macros,
commit 0c6f41f5cdf5bb33111d3b21c7daae50fc636456
Author: Nikodemus Siivola <nikodemus at random-state.net>
Date: Thu Sep 23 18:20:35 2010 +0300
added .gitignore -files
-----------------------------------------------------------------------
Summary of changes:
.gitignore | 4 +++
doc/.gitignore | 3 ++
macros.lisp | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
package.lisp | 3 ++
4 files changed, 84 insertions(+), 0 deletions(-)
create mode 100644 .gitignore
create mode 100644 doc/.gitignore
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e832e94
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.fasl
+*~
+\#*
+*.patch
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 0000000..f22577b
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1,3 @@
+alexandria
+include
+
diff --git a/macros.lisp b/macros.lisp
index 75ff3f4..4450435 100644
--- a/macros.lisp
+++ b/macros.lisp
@@ -230,3 +230,77 @@ Signals a PROGRAM-ERROR is the lambda-list is malformed."
(simple-program-error "Invalid ordinary lambda-list:~% ~S" lambda-list)))))))
(values (nreverse required) (nreverse optional) rest (nreverse keys)
allow-other-keys (nreverse aux))))
+
+;;;; DESTRUCTURING-*CASE
+
+(defun expand-destructuring-case (key clauses case)
+ (once-only (key)
+ `(if (typep ,key 'cons)
+ (,case (car ,key)
+ ,@(mapcar (lambda (clause)
+ (destructuring-bind ((keys . lambda-list) &body body) clause
+ `(,keys
+ (destructuring-bind ,lambda-list (cdr ,key)
+ , at body))))
+ clauses))
+ (error "Invalid key to DESTRUCTURING-~S: ~S" ',case ,key))))
+
+(defmacro destructuring-case (keyform &body clauses)
+ "DESTRUCTURING-CASE, -CCASE, and -ECASE are a combination of CASE and DESTRUCTURING-BIND.
+KEYFORM must evaluate to a CONS.
+
+Clauses are of the form:
+
+ ((CASE-KEYS . DESTRUCTURING-LAMBDA-LIST) FORM*)
+
+The clause whose CASE-KEYS matches CAR of KEY, as if by CASE, CCASE, or ECASE,
+is selected, and FORMs are then executed with CDR of KEY is destructured and
+bound by the DESTRUCTURING-LAMBDA-LIST.
+
+Example:
+
+ (defun dcase (x)
+ (destructuring-case x
+ ((:foo a b)
+ (format nil \"foo: ~S, ~S\" a b))
+ ((:bar &key a b)
+ (format nil \"bar, ~S, ~S\" a b))
+ (((:alt1 :alt2) a)
+ (format nil \"alt: ~S\" a))
+ ((t &rest rest)
+ (format nil \"unknown: ~S\" rest))))
+
+ (dcase (list :foo 1 2)) ; => \"foo: 1, 2\"
+ (dcase (list :bar :a 1 :b 2)) ; => \"bar: 1, 2\"
+ (dcase (list :alt1 1)) ; => \"alt: 1\"
+ (dcase (list :alt2 2)) ; => \"alt: 2\"
+ (dcase (list :quux 1 2 3)) ; => \"unknown: 1, 2, 3\"
+
+ (defun decase (x)
+ (destructuring-case x
+ ((:foo a b)
+ (format nil \"foo: ~S, ~S\" a b))
+ ((:bar &key a b)
+ (format nil \"bar, ~S, ~S\" a b))
+ (((:alt1 :alt2) a)
+ (format nil \"alt: ~S\" a))))
+
+ (decase (list :foo 1 2)) ; => \"foo: 1, 2\"
+ (decase (list :bar :a 1 :b 2)) ; => \"bar: 1, 2\"
+ (decase (list :alt1 1)) ; => \"alt: 1\"
+ (decase (list :alt2 2)) ; => \"alt: 2\"
+ (decase (list :quux 1 2 3)) ; =| error
+"
+ (expand-destructuring-case keyform clauses 'case))
+
+(defmacro destructuring-ccase (keyform &body clauses)
+ (expand-destructuring-case keyform clauses 'ccase))
+
+(defmacro destructuring-ecase (keyform &body clauses)
+ (expand-destructuring-case keyform clauses 'ecase))
+
+(dolist (name '(destructuring-ccase destructuring-ecase))
+ (setf (documentation name 'function) (documentation 'destructuring-case 'function)))
+
+
+
diff --git a/package.lisp b/package.lisp
index b5ce17b..57c3526 100644
--- a/package.lisp
+++ b/package.lisp
@@ -233,4 +233,7 @@
#:symbolicate
#:assoc-value
#:rassoc-value
+ #:destructuring-case
+ #:destructuring-ccase
+ #:destructuring-ecase
))
--
Alexandria hooks/post-receive
More information about the alexandria-cvs
mailing list