1.3.0 permalink Arrow_down_16x16

condp

clojure.core

  • (condp pred expr & clauses)
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.

7 Examples top

  • ;; Taken from the excellent clojure tutorial:
    ;; http://java.ociweb.com/mark/clojure/article.html
    
    user=> (print "Enter a number: ")
    user=> (flush) ; stays in a buffer otherwise
    user=> (let [reader (java.io.BufferedReader. *in*) ; stdin
                 line (.readLine reader)
                 value (try
                         (Integer/parseInt line)
                         (catch NumberFormatException e line))] ;use string val if not int
             (println
               (condp = value
                 1 "one"
                 2 "two"
                 3 "three"
                 (str "unexpected value, \"" value \")))
             (println
               (condp instance? value
                 Number (* value 2)
                 String (* (count value) 2))))
    
  • user=> (condp some [1 2 3 4]
             #{0 6 7} :>> inc
             #{4 5 9} :>> dec
             #{1 2 3} :>> #(+ % 3))
    
    3
  • user=> (condp some [1 2 3 4]
             #{0 6 7} :>> inc
             #{5 9}   :>> dec)
    
    java.lang.IllegalArgumentException: No matching clause: [1 2 3 4]
  • user=> (condp (comp seq re-seq) "foo=bar"
             #"[+](\w+)"    :>> #(vector (-> % first (nth 1) keyword) true)
             #"[-](\w+)"    :>> #(vector (-> % first (nth 1) keyword) false)
             #"(\w+)=(\S+)" :>> #(let [x (first %)]
                                   [(keyword (nth x 1)) (nth x 2)]))
    
    [:foo "bar"]
  • ;; See examples for "if" explaining Clojure's idea of logical true
    ;; and logical false.
  • ;;this is with liberator
    ;;branching on request method
    (defresource my-resource
      :exists? (fn [{:keys [db] {query-params :query-params 
                                 body :body 
                                 method :request-method} 
                     :request}]
                 
                 (condp = method
                   :get (my-get-exists-fn)
                   :post (my-post-exists-fn))))
  • ;; a recursive function to calculate length
    ;; same as 'count'
    (defn length [lst]
        (condp = lst
            (list) 0 ; if empty list result 0
            (+ 1 (length (rest lst))))) ; default expression
    
    user=> (length '(1 2 3))
    
    user=> 3
Log in to add / edit an example.

See Also top

Log in to add a see also.

Plus_12x12 Minus_12x12 Source clojure/core.clj:5595 top

(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."
  {:added "1.0"}

  [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. (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))))
Vars in clojure.core/condp:
Used in 0 other vars

Comments top

No comments for condp. Log in to add a comment.