hi,

  i'd like switch to, just like case and typecase do, allow multiple
  values in the 'value' position of the condition:

  (switch (foo)
    ((bar baz) ...))

  So the attached patch checks for the key form being a cons and, if so,
  expands into a (member value :test test) instead of (test value)
  form. Of course, this means that your key values can no longer be
  forms, so this may break existing code. I don't have any code which
  actually uses a function call in the value form of the clause (and a
  quick grep over my locally installed lisp libs shows nobody else does
  either), so i'm ok with the change, but i can understand if others
  don't agree.

>From 59ec2cc21b43eb9037758d2b5494206b4e464f11 Mon Sep 17 00:00:00 2001
From: Marco Baringer <m...@bese.it>
Date: Sun, 11 Nov 2012 14:49:41 +0100
Subject: [PATCH 1/2] Support multiple keys in switch clauses (similar to how
 case works).

---
 control-flow.lisp | 42 ++++++++++++++++++++++--------------------
 1 file changed, 22 insertions(+), 20 deletions(-)

diff --git a/control-flow.lisp b/control-flow.lisp
index f262443..0175a17 100644
--- a/control-flow.lisp
+++ b/control-flow.lisp
@@ -10,26 +10,28 @@ like #'eq and 'eq."
 
 (defun generate-switch-body (whole object clauses test key &optional default)
   (with-gensyms (value)
-    (setf test (extract-function-name test))
-    (setf key (extract-function-name key))
-    (when (and (consp default)
-               (member (first default) '(error cerror)))
-      (setf default `(,@default "No keys match in SWITCH. Testing against ~S with ~S."
-                      ,value ',test)))
-    `(let ((,value (,key ,object)))
-      (cond ,@(mapcar (lambda (clause)
-                        (if (member (first clause) '(t otherwise))
-                            (progn
-                              (when default
-                                (error "Multiple default clauses or illegal use of a default clause in ~S."
-                                       whole))
-                              (setf default `(progn ,@(rest clause)))
-                              '(()))
-                            (destructuring-bind (key-form &body forms) clause
-                              `((,test ,value ,key-form)
-                                ,@forms))))
-                      clauses)
-            (t ,default)))))
+    (let ((test-name (extract-function-name test))
+          (key-function-name (extract-function-name key)))
+      (when (and (consp default)
+                 (member (first default) '(error cerror)))
+        (setf default `(,@default "No keys match in SWITCH. Testing against ~S with ~S."
+                           ,value ',test-name)))
+      `(let ((,value (,key-function-name ,object)))
+         (cond ,@(mapcar (lambda (clause)
+                           (if (member (first clause) '(t otherwise))
+                               (progn
+                                 (when default
+                                   (error "Multiple default clauses or illegal use of a default clause in ~S."
+                                          whole))
+                                 (setf default `(progn ,@(rest clause)))
+                                 '(()))
+                               (destructuring-bind (key-form &body forms) clause
+                                 (let ((condition (if (consp key-form)
+                                                      `(member ,value ',key-form :test ,test)
+                                                      `(,test-name ,value ,key-form))))
+                                   `(,condition ,@forms)))))
+                         clauses)
+               (t ,default))))))
 
 (defmacro switch (&whole whole (object &key (test 'eql) (key 'identity))
                          &body clauses)
-- 
1.7.12.3


--
-marco
_______________________________________________
alexandria-devel mailing list
alexandria-devel@common-lisp.net
http://lists.common-lisp.net/cgi-bin/mailman/listinfo/alexandria-devel

Reply via email to