Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 224 lines (188 sloc) 7.264 kb
04eb37e @scgilardi minimal port to Clojure SVN 1094+ of seq-utils import-static trace enum ...
scgilardi authored
1 ;;; seq_utils.clj -- Sequence utilities for Clojure
2
3 ;; by Stuart Sierra, http://stuartsierra.com/
3fd57b7 seq-utils: new multimethod seq-on
Konrad Hinsen authored
4 ;; last updated March 2, 2009
04eb37e @scgilardi minimal port to Clojure SVN 1094+ of seq-utils import-static trace enum ...
scgilardi authored
5
7cfb20f @stuartsierra Stuart Sierra: Moved libs I wrote to Eclipse Public License 1.0
stuartsierra authored
6 ;; Copyright (c) Stuart Sierra, 2008. All rights reserved. The use
7 ;; and distribution terms for this software are covered by the Eclipse
8 ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
9 ;; which can be found in the file epl-v10.html at the root of this
04eb37e @scgilardi minimal port to Clojure SVN 1094+ of seq-utils import-static trace enum ...
scgilardi authored
10 ;; distribution. By using this software in any fashion, you are
11 ;; agreeing to be bound by the terms of this license. You must not
12 ;; remove this notice, or any other, from this software.
13
14
7240a2a @stuartsierra seq_utils.clj: BREAKING CHANGE: swap argument order of "includes?"
stuartsierra authored
15 ;; Change Log
16 ;;
17 ;; January 10, 2009 (Stuart Sierra):
18 ;;
19 ;; * BREAKING CHANGE: "includes?" now takes collection as first
20 ;; argument. This is more consistent with Clojure collection
21 ;; functions; see discussion at http://groups.google.com/group/clojure/browse_thread/thread/8b2c8dc96b39ddd7/a8866d34b601ff43
22
23
86e9001 @tomfaulhaber Lots 'o doc strings
tomfaulhaber authored
24 (ns
25 #^{:author "Stuart Sierra (and others)",
26 :doc "Sequence utilities for Clojure"}
2d2c200 @Chouser seq-utils: Add fill-queue
Chouser authored
27 clojure.contrib.seq-utils
28 (:import (java.util.concurrent LinkedBlockingQueue TimeUnit)
29 (java.lang.ref WeakReference)))
04eb37e @scgilardi minimal port to Clojure SVN 1094+ of seq-utils import-static trace enum ...
scgilardi authored
30
31
32 ;; 'flatten' written by Rich Hickey,
33 ;; see http://groups.google.com/group/clojure/msg/385098fabfcaad9b
34 (defn flatten
35 "Takes any nested combination of sequential things (lists, vectors,
2c2cf4b @stuartsierra seq_utils.clj: fixed flatten to return nil for nil
stuartsierra authored
36 etc.) and returns their contents as a single, flat sequence.
37 (flatten nil) returns nil."
04eb37e @scgilardi minimal port to Clojure SVN 1094+ of seq-utils import-static trace enum ...
scgilardi authored
38 [x]
2c2cf4b @stuartsierra seq_utils.clj: fixed flatten to return nil for nil
stuartsierra authored
39 (filter (complement sequential?)
40 (rest (tree-seq sequential? seq x))))
04eb37e @scgilardi minimal port to Clojure SVN 1094+ of seq-utils import-static trace enum ...
scgilardi authored
41
42 (defn separate
43 "Returns a vector:
44 [ (filter f s), (filter (complement f) s) ]"
45 [f s]
46 [(filter f s) (filter (complement f) s)])
47
48 (defn includes?
7240a2a @stuartsierra seq_utils.clj: BREAKING CHANGE: swap argument order of "includes?"
stuartsierra authored
49 "Returns true if coll contains something equal (with =) to x,
50 in linear time."
51 [coll x]
52 (if (some (fn [y] (= y x)) coll)
04eb37e @scgilardi minimal port to Clojure SVN 1094+ of seq-utils import-static trace enum ...
scgilardi authored
53 true false))
54
55 (defn indexed
56 "Returns a lazy sequence of [index, item] pairs, where items come
57 from 's' and indexes count up from zero.
58
59 (indexed '(a b c d)) => ([0 a] [1 b] [2 c] [3 d])"
60 [s]
61 (map vector (iterate inc 0) s))
62
63 ;; group-by written by Rich Hickey;
64 ;; see http://paste.lisp.org/display/64190
baef7d3 @stuartsierra seq_utils.clj: fixed misplaced doc strings (report by Perry Trolard)
stuartsierra authored
65 (defn group-by
04eb37e @scgilardi minimal port to Clojure SVN 1094+ of seq-utils import-static trace enum ...
scgilardi authored
66 "Returns a sorted map of the elements of coll keyed by the result of
67 f on each element. The value at each key will be a vector of the
68 corresponding elements, in the order they appeared in coll."
baef7d3 @stuartsierra seq_utils.clj: fixed misplaced doc strings (report by Perry Trolard)
stuartsierra authored
69 [f coll]
04eb37e @scgilardi minimal port to Clojure SVN 1094+ of seq-utils import-static trace enum ...
scgilardi authored
70 (reduce
71 (fn [ret x]
72 (let [k (f x)]
73 (assoc ret k (conj (get ret k []) x))))
74 (sorted-map) coll))
75
3d662f2 @stuartsierra seq_utils.clj: Issue 35: fixed partition-by to only call f once on each ...
stuartsierra authored
76 ;; partition-by originally written by Rich Hickey;
77 ;; modified by Stuart Sierra
baef7d3 @stuartsierra seq_utils.clj: fixed misplaced doc strings (report by Perry Trolard)
stuartsierra authored
78 (defn partition-by
04eb37e @scgilardi minimal port to Clojure SVN 1094+ of seq-utils import-static trace enum ...
scgilardi authored
79 "Applies f to each value in coll, splitting it each time f returns
80 a new value. Returns a lazy seq of lazy seqs."
baef7d3 @stuartsierra seq_utils.clj: fixed misplaced doc strings (report by Perry Trolard)
stuartsierra authored
81 [f coll]
04eb37e @scgilardi minimal port to Clojure SVN 1094+ of seq-utils import-static trace enum ...
scgilardi authored
82 (when-let [s (seq coll)]
3d662f2 @stuartsierra seq_utils.clj: Issue 35: fixed partition-by to only call f once on each ...
stuartsierra authored
83 (let [fst (first s)
84 fv (f fst)
85 run (cons fst (take-while #(= fv (f %)) (rest s)))]
d5701c3 @Chouser Merged lazy branch into trunk:
Chouser authored
86 (lazy-seq
c77a6da @stuartsierra seq_utils.clj: fix error using wrong name in last revision
stuartsierra authored
87 (cons run (partition-by f (drop (count run) s)))))))
77e3f00 @stuartsierra seq_utils.clj: added "frequencies"
stuartsierra authored
88
89 (defn frequencies
90 "Returns a map from distinct items in coll to the number of times
91 they appear."
92 [coll]
93 (reduce (fn [counts x]
94 (assoc counts x (inc (get counts x 0))))
95 {} coll))
422ec0a @cgrand added rec-cat, rec-cons and reductions
cgrand authored
96
97 ;; recursive sequence helpers by Christophe Grand
98 ;; see http://clj-me.blogspot.com/2009/01/recursive-seqs.html
0cb2904 @cgrand replaced rec-cons by rec-seq
cgrand authored
99 (defmacro rec-seq
100 "Similar to lazy-seq but binds the resulting seq to the supplied
101 binding-name, allowing for recursive expressions."
102 [binding-name & body]
188682d @cgrand back to a mutation-based rec-seq
cgrand authored
103 `(let [s# (atom nil)]
38e603d @cgrand I keep forgetting the existence of reset!
cgrand authored
104 (reset! s# (lazy-seq (let [~binding-name @s#] ~@body)))))
188682d @cgrand back to a mutation-based rec-seq
cgrand authored
105
422ec0a @cgrand added rec-cat, rec-cons and reductions
cgrand authored
106 (defmacro rec-cat
0cb2904 @cgrand replaced rec-cons by rec-seq
cgrand authored
107 "Similar to lazy-cat but binds the resulting sequence to the supplied
108 binding-name, allowing for recursive expressions."
109 [binding-name & exprs]
110 `(rec-seq ~binding-name (lazy-cat ~@exprs)))
422ec0a @cgrand added rec-cat, rec-cons and reductions
cgrand authored
111
112
113 ;; reductions by Chris Houser
114 ;; see http://groups.google.com/group/clojure/browse_thread/thread/3edf6e82617e18e0/58d9e319ad92aa5f?#58d9e319ad92aa5f
115 (defn reductions
116 "Returns a lazy seq of the intermediate values of the reduction (as
117 per reduce) of coll by f, starting with init."
118 ([f coll]
119 (if (seq coll)
0cb2904 @cgrand replaced rec-cons by rec-seq
cgrand authored
120 (rec-seq self (cons (first coll) (map f self (rest coll))))
422ec0a @cgrand added rec-cat, rec-cons and reductions
cgrand authored
121 (cons (f) nil)))
122 ([f init coll]
0cb2904 @cgrand replaced rec-cons by rec-seq
cgrand authored
123 (rec-seq self (cons init (map f self coll)))))
f4bc200 @scgilardi fix issue 29: move sequence functions from lazy_seqs to seq_utils
scgilardi authored
124
125 (defn rotations
126 "Returns a lazy seq of all rotations of a seq"
127 [x]
128 (if (seq x)
129 (map
130 (fn [n _]
131 (lazy-cat (drop n x) (take n x)))
132 (iterate inc 0) x)
133 (list nil)))
134
64d7920 @scgilardi fix issue 28: add step arg to partition-all, also fix doc string for ran...
scgilardi authored
135 (defn partition-all
136 "Returns a lazy sequence of lists like clojure.core/partition, but may
137 include lists with fewer than n items at the end."
138 ([n coll]
139 (partition-all n n coll))
140 ([n step coll]
141 (lazy-seq
142 (when-let [s (seq coll)]
143 (cons (take n s) (partition-all n step (drop step s)))))))
144
f4bc200 @scgilardi fix issue 29: move sequence functions from lazy_seqs to seq_utils
scgilardi authored
145 (defn shuffle
146 "Return a random permutation of coll"
147 [coll]
148 (let [l (java.util.ArrayList. coll)]
149 (java.util.Collections/shuffle l)
150 (seq l)))
151
64d7920 @scgilardi fix issue 28: add step arg to partition-all, also fix doc string for ran...
scgilardi authored
152 (defn rand-elt
f4bc200 @scgilardi fix issue 29: move sequence functions from lazy_seqs to seq_utils
scgilardi authored
153 "Return a random element of this seq"
64d7920 @scgilardi fix issue 28: add step arg to partition-all, also fix doc string for ran...
scgilardi authored
154 [s]
f4bc200 @scgilardi fix issue 29: move sequence functions from lazy_seqs to seq_utils
scgilardi authored
155 (nth s (rand-int (count s))))
3fd57b7 seq-utils: new multimethod seq-on
Konrad Hinsen authored
156
157
86e9001 @tomfaulhaber Lots 'o doc strings
tomfaulhaber authored
158 ;; seq-on written by Konrad Hinsen
3fd57b7 seq-utils: new multimethod seq-on
Konrad Hinsen authored
159 (defmulti seq-on
160 "Returns a seq on the object s. Works like the built-in seq but as
161 a multimethod that can have implementations for new classes and types."
162 {:arglists '([s])}
163 type)
164
165 (defmethod seq-on :default
166 [s]
167 (seq s))
0c92dbf @stuartsierra seq_utils.clj: added "seek" function, for (first (filter ...))
stuartsierra authored
168
169
8322249 @stuartsierra seq_utils.clj: renamed "seek" to "find-first"
stuartsierra authored
170 (defn find-first
0c92dbf @stuartsierra seq_utils.clj: added "seek" function, for (first (filter ...))
stuartsierra authored
171 "Returns the first item of coll for which (pred item) returns logical true.
172 Consumes sequences up to the first match, will consume the entire sequence
173 and return nil if no match is found."
174 [pred coll]
175 (first (filter pred coll)))
2d2c200 @Chouser seq-utils: Add fill-queue
Chouser authored
176
da640a5 @Chouser seq-utils: Fix fill-queue attribution
Chouser authored
177 ; based on work related to Rich Hickey's seque.
178 ; blame Chouser for anything broken or ugly.
2d2c200 @Chouser seq-utils: Add fill-queue
Chouser authored
179 (defn fill-queue
180 "filler-func will be called in another thread with a single arg
181 'fill'. filler-func may call fill repeatedly with one arg each
182 time which will be pushed onto a queue, blocking if needed until
183 this is possible. fill-queue will return a lazy seq of the values
184 filler-func has pushed onto the queue, blocking if needed until each
185 next element becomes available. filler-func's return value is ignored."
186 ([filler-func & optseq]
187 (let [opts (apply array-map optseq)
188 apoll (:alive-poll opts 1)
189 q (LinkedBlockingQueue. (:queue-size opts 1))
190 NIL (Object.) ;nil sentinel since LBQ doesn't support nils
191 weak-target (Object.)
192 alive? (WeakReference. weak-target)
193 fill (fn fill [x]
194 (if (.get alive?)
195 (if (.offer q (if (nil? x) NIL x) apoll TimeUnit/SECONDS)
196 x
197 (recur x))
198 (throw (Exception. "abandoned"))))
199 f (future
200 (try
201 (filler-func fill)
202 (finally
203 (.put q q))) ;q itself is eos sentinel
204 nil)] ; set future's value to nil
205 ((fn drain []
206 weak-target ; force closing over this object
207 (lazy-seq
208 (let [x (.take q)]
209 (if (identical? x q)
210 @f ;will be nil, touch just to propagate errors
211 (cons (if (identical? x NIL) nil x)
212 (drain))))))))))
213
1640c04 positions takes only a predicate, per Rich's feedback
Aaron Bedra and Stuart Halloway authored
214 (defn positions
215 "Returns a lazy sequence containing the positions at which pred
216 is true for items in coll."
217 [pred coll]
b70cba0 add seq-utils/positions
Aaron Bedra and Stuart Halloway authored
218 (for [[idx elt] (indexed coll) :when (pred elt)] idx))
219
220
221
222
223
Something went wrong with that request. Please try again.