summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-12-21 19:54:56 +0000
committerRich Hickey <richhickey@gmail.com>2008-12-21 19:54:56 +0000
commite7f5352fd0c2e401b31f7b7fb2a8e7d94a7a6344 (patch)
tree913d7af0b7485b1efbf97f5ab14181da4967486a /src
parentf922d2f4e9c536103cea8a3c3130fef9529a3396 (diff)
added condp, with input from Stuart Sierra and Meikel Brandmeyer
Diffstat (limited to 'src')
-rw-r--r--src/clj/clojure/core.clj41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index cf19ec54..0b58b4ff 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -3612,6 +3612,47 @@
(swap! mem assoc args ret)
ret)))))
+(defmacro condp
+ "Takes a binary predicate, an expression, and a set of clauses.
+ Each clause can take the form of either:
+
+ test-expr result-expr
+
+ test-expr :>> result-fn
+
+ Note :>> is an ordinary keyword.
+
+ For each clause, (pred test-expr expr) is evaluated. If it returns
+ logical true, the clause is a match. If a binary clause matches, the
+ result-expr is returned, if a ternary clause matches, its result-fn,
+ which must be a unary function, is called with the result of the
+ predicate as its argument, the result of that call being the return
+ value of condp. A single default expression can follow the clauses,
+ and its value will be returned if no clause matches. If no default
+ expression is provided and no clause matches, an
+ IllegalArgumentException is thrown."
+
+ [pred expr & clauses]
+ (let [gpred (gensym "pred__")
+ gexpr (gensym "expr__")
+ emit (fn emit [pred expr args]
+ (let [[[a b c :as clause] more]
+ (split-at (if (= :>> (second args)) 3 2) args)
+ n (count clause)]
+ (cond
+ (= 0 n) `(throw (IllegalArgumentException. "No matching clause"))
+ (= 1 n) a
+ (= 2 n) `(if (~pred ~a ~expr)
+ ~b
+ ~(emit pred expr more))
+ :else `(if-let [p# (~pred ~a ~expr)]
+ (~c p#)
+ ~(emit pred expr more)))))
+ gres (gensym "res__")]
+ `(let [~gpred ~pred
+ ~gexpr ~expr]
+ ~(emit gpred gexpr clauses))))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; helper files ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(load "core_proxy")