condp

macrosince v0.0-927 clojure.core/condpEdit
(condp pred expr & clauses)

Details:

Takes a binary predicate, an expression, and a set of clauses. There are two kinds of clauses:

Binary clause: test-expr result-expr

Ternary clause: 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, its result-expr is returned.

If a ternary clause matches, its result-fn is called with the result of the predicate and returned by condp. result-fn should take one argument.

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 Error is thrown.


See Also:


Source docstring:
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 Error is thrown.
Source code @ clojurescript:src/main/clojure/cljs/core.cljc
(core/defmacro condp
  [pred expr & clauses]
  (core/let [gpred (gensym "pred__")
             gexpr (gensym "expr__")
             emit (core/fn emit [pred expr args]
                    (core/let [[[a b c :as clause] more]
                               (split-at (if (= :>> (second args)) 3 2) args)
                               n (count clause)]
                      (core/cond
                        (= 0 n) `(throw (js/Error. (cljs.core/str "No matching clause: " ~expr)))
                        (= 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))))