summaryrefslogtreecommitdiff
path: root/vim/bundle/slimv/swank-clojure/swank/util.clj
blob: 756e6f054d9e197bdcc9a966e44f7f24cf6792bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
(ns swank.util
  (:import (java.io StringReader)
           (clojure.lang LineNumberingPushbackReader)))

(defmacro one-of?
  "Short circuiting value comparison."
  ([val & possible]
     (let [v (gensym)]
       `(let [~v ~val]
          (or ~@(map (fn [p] `(= ~v ~p)) possible))))))

(defn find-first
  "Returns the first entry in a coll matches a given predicate."
  ([coll] (find-first identity coll))
  ([pred coll]
     (first (filter pred coll))))

(defn position
  "Finds the first position of an item that matches a given predicate
   within col. Returns nil if not found. Optionally provide a start
   offset to search from."
  ([pred coll] (position pred coll 0))
  ([pred coll start]
     (loop [coll (drop start coll), i start]
       (when (seq coll)
         (if (pred (first coll))
           i
           (recur (rest coll) (inc i))))))
  {:tag Integer})

(when-not (ns-resolve 'clojure.core 'group-by)
  ;; TODO: not sure why eval is necessary here; breaks without it.
  (eval '(defn group-by
           "Categorizes elements within a coll into a map based on a function."
           ([f coll]
              (reduce
               (fn [ret x]
                 (let [k (f x)]
                   (assoc ret k (conj (get ret k []) x))))
               {})))))

(when-not (ns-resolve 'clojure.core 'flatten)
  (eval '(defn flatten [x]
           (filter (complement sequential?)
                   (rest (tree-seq sequential? seq x))))))

(defmacro returning [[var ret] & body]
  `(let [~var ~ret]
     ~@body
     ~var))


(defn deep-replace [smap coll]
  (map #(if (or (seq? %) (vector? %))
          (deep-replace smap %)
          %)
       (replace smap coll)))

(defmacro keep-bindings [bindings f]
  (let [bind-vars (take (count bindings) (repeatedly gensym))]
    `(let [~@(interleave bind-vars bindings)]
       (fn [& args#]
         (binding [~@(interleave bindings bind-vars)]
           (apply ~f args#))))))

(defmacro continuously [& body]
  `(loop [] ~@body (recur)))

(defmacro failing-gracefully [& body]
  `(try
    ~@body
    (catch Throwable _# nil)))