Mercurial > lasercutter
comparison src/clojure/contrib/seq_utils.clj @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
9:35cf337adfcf | 10:ef7dbbd6452c |
---|---|
1 ;;; seq_utils.clj -- Sequence utilities for Clojure | |
2 | |
3 ;; by Stuart Sierra, http://stuartsierra.com/ | |
4 ;; last updated March 2, 2009 | |
5 | |
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 | |
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 | |
15 ;; Change Log | |
16 ;; | |
17 ;; DEPRECATED in 1.2. Some functions promoted to clojure.core and some | |
18 ;; moved to c.c.seq | |
19 ;; | |
20 ;; January 10, 2009 (Stuart Sierra): | |
21 ;; | |
22 ;; * BREAKING CHANGE: "includes?" now takes collection as first | |
23 ;; argument. This is more consistent with Clojure collection | |
24 ;; functions; see discussion at http://groups.google.com/group/clojure/browse_thread/thread/8b2c8dc96b39ddd7/a8866d34b601ff43 | |
25 ;; | |
26 | |
27 (ns | |
28 ^{:author "Stuart Sierra (and others)", | |
29 :deprecated "1.2" | |
30 :doc "Sequence utilities for Clojure"} | |
31 clojure.contrib.seq-utils | |
32 (:import (java.util.concurrent LinkedBlockingQueue TimeUnit) | |
33 (java.lang.ref WeakReference)) | |
34 (:refer-clojure :exclude [frequencies shuffle partition-by reductions partition-all group-by flatten])) | |
35 | |
36 | |
37 ;; 'flatten' written by Rich Hickey, | |
38 ;; see http://groups.google.com/group/clojure/msg/385098fabfcaad9b | |
39 (defn flatten | |
40 "DEPRECATED. Prefer clojure.core version. | |
41 Takes any nested combination of sequential things (lists, vectors, | |
42 etc.) and returns their contents as a single, flat sequence. | |
43 (flatten nil) returns nil." | |
44 {:deprecated "1.2"} | |
45 [x] | |
46 (filter (complement sequential?) | |
47 (rest (tree-seq sequential? seq x)))) | |
48 | |
49 (defn separate | |
50 "Returns a vector: | |
51 [ (filter f s), (filter (complement f) s) ]" | |
52 [f s] | |
53 [(filter f s) (filter (complement f) s)]) | |
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 | |
65 (defn group-by | |
66 "DEPRECATED. Prefer clojure.core version. | |
67 Returns a sorted map of the elements of coll keyed by the result of | |
68 f on each element. The value at each key will be a vector of the | |
69 corresponding elements, in the order they appeared in coll." | |
70 {:deprecated "1.2"} | |
71 [f coll] | |
72 (reduce | |
73 (fn [ret x] | |
74 (let [k (f x)] | |
75 (assoc ret k (conj (get ret k []) x)))) | |
76 (sorted-map) coll)) | |
77 | |
78 ;; partition-by originally written by Rich Hickey; | |
79 ;; modified by Stuart Sierra | |
80 (defn partition-by | |
81 "DEPRECATED. Prefer clojure.core version. | |
82 Applies f to each value in coll, splitting it each time f returns | |
83 a new value. Returns a lazy seq of lazy seqs." | |
84 {:deprecated "1.2"} | |
85 [f coll] | |
86 (when-let [s (seq coll)] | |
87 (let [fst (first s) | |
88 fv (f fst) | |
89 run (cons fst (take-while #(= fv (f %)) (rest s)))] | |
90 (lazy-seq | |
91 (cons run (partition-by f (drop (count run) s))))))) | |
92 | |
93 (defn frequencies | |
94 "DEPRECATED. Prefer clojure.core version. | |
95 Returns a map from distinct items in coll to the number of times | |
96 they appear." | |
97 {:deprecated "1.2"} | |
98 [coll] | |
99 (reduce (fn [counts x] | |
100 (assoc counts x (inc (get counts x 0)))) | |
101 {} coll)) | |
102 | |
103 ;; recursive sequence helpers by Christophe Grand | |
104 ;; see http://clj-me.blogspot.com/2009/01/recursive-seqs.html | |
105 (defmacro rec-seq | |
106 "Similar to lazy-seq but binds the resulting seq to the supplied | |
107 binding-name, allowing for recursive expressions." | |
108 [binding-name & body] | |
109 `(let [s# (atom nil)] | |
110 (reset! s# (lazy-seq (let [~binding-name @s#] ~@body))))) | |
111 | |
112 (defmacro rec-cat | |
113 "Similar to lazy-cat but binds the resulting sequence to the supplied | |
114 binding-name, allowing for recursive expressions." | |
115 [binding-name & exprs] | |
116 `(rec-seq ~binding-name (lazy-cat ~@exprs))) | |
117 | |
118 | |
119 ;; reductions by Chris Houser | |
120 ;; see http://groups.google.com/group/clojure/browse_thread/thread/3edf6e82617e18e0/58d9e319ad92aa5f?#58d9e319ad92aa5f | |
121 (defn reductions | |
122 "DEPRECATED. Prefer clojure.core version. | |
123 Returns a lazy seq of the intermediate values of the reduction (as | |
124 per reduce) of coll by f, starting with init." | |
125 {:deprecated "1.2"} | |
126 ([f coll] | |
127 (if (seq coll) | |
128 (rec-seq self (cons (first coll) (map f self (rest coll)))) | |
129 (cons (f) nil))) | |
130 ([f init coll] | |
131 (rec-seq self (cons init (map f self coll))))) | |
132 | |
133 (defn rotations | |
134 "Returns a lazy seq of all rotations of a seq" | |
135 [x] | |
136 (if (seq x) | |
137 (map | |
138 (fn [n _] | |
139 (lazy-cat (drop n x) (take n x))) | |
140 (iterate inc 0) x) | |
141 (list nil))) | |
142 | |
143 (defn partition-all | |
144 "DEPRECATED. Prefer clojure.core version. | |
145 Returns a lazy sequence of lists like clojure.core/partition, but may | |
146 include lists with fewer than n items at the end." | |
147 {:deprecated "1.2"} | |
148 ([n coll] | |
149 (partition-all n n coll)) | |
150 ([n step coll] | |
151 (lazy-seq | |
152 (when-let [s (seq coll)] | |
153 (cons (take n s) (partition-all n step (drop step s))))))) | |
154 | |
155 (defn shuffle | |
156 "DEPRECATED. Prefer clojure.core version. | |
157 Return a random permutation of coll" | |
158 {:deprecated "1.2"} | |
159 [coll] | |
160 (let [l (java.util.ArrayList. coll)] | |
161 (java.util.Collections/shuffle l) | |
162 (seq l))) | |
163 | |
164 (defn rand-elt | |
165 "DEPRECATED. Prefer clojure.core/rand-nth. | |
166 Return a random element of this seq" | |
167 {:deprecated "1.2"} | |
168 [s] | |
169 (nth s (rand-int (count s)))) | |
170 | |
171 | |
172 ;; seq-on written by Konrad Hinsen | |
173 (defmulti seq-on | |
174 "Returns a seq on the object s. Works like the built-in seq but as | |
175 a multimethod that can have implementations for new classes and types." | |
176 {:arglists '([s])} | |
177 type) | |
178 | |
179 (defmethod seq-on :default | |
180 [s] | |
181 (seq s)) | |
182 | |
183 | |
184 (defn find-first | |
185 "Returns the first item of coll for which (pred item) returns logical true. | |
186 Consumes sequences up to the first match, will consume the entire sequence | |
187 and return nil if no match is found." | |
188 [pred coll] | |
189 (first (filter pred coll))) | |
190 | |
191 ; based on work related to Rich Hickey's seque. | |
192 ; blame Chouser for anything broken or ugly. | |
193 (defn fill-queue | |
194 "filler-func will be called in another thread with a single arg | |
195 'fill'. filler-func may call fill repeatedly with one arg each | |
196 time which will be pushed onto a queue, blocking if needed until | |
197 this is possible. fill-queue will return a lazy seq of the values | |
198 filler-func has pushed onto the queue, blocking if needed until each | |
199 next element becomes available. filler-func's return value is ignored." | |
200 ([filler-func & optseq] | |
201 (let [opts (apply array-map optseq) | |
202 apoll (:alive-poll opts 1) | |
203 q (LinkedBlockingQueue. (:queue-size opts 1)) | |
204 NIL (Object.) ;nil sentinel since LBQ doesn't support nils | |
205 weak-target (Object.) | |
206 alive? (WeakReference. weak-target) | |
207 fill (fn fill [x] | |
208 (if (.get alive?) | |
209 (if (.offer q (if (nil? x) NIL x) apoll TimeUnit/SECONDS) | |
210 x | |
211 (recur x)) | |
212 (throw (Exception. "abandoned")))) | |
213 f (future | |
214 (try | |
215 (filler-func fill) | |
216 (finally | |
217 (.put q q))) ;q itself is eos sentinel | |
218 nil)] ; set future's value to nil | |
219 ((fn drain [] | |
220 weak-target ; force closing over this object | |
221 (lazy-seq | |
222 (let [x (.take q)] | |
223 (if (identical? x q) | |
224 @f ;will be nil, touch just to propagate errors | |
225 (cons (if (identical? x NIL) nil x) | |
226 (drain)))))))))) | |
227 | |
228 (defn positions | |
229 "Returns a lazy sequence containing the positions at which pred | |
230 is true for items in coll." | |
231 [pred coll] | |
232 (for [[idx elt] (indexed coll) :when (pred elt)] idx)) | |
233 | |
234 (defn includes? | |
235 "Returns true if coll contains something equal (with =) to x, | |
236 in linear time. Deprecated. Prefer 'contains?' for key testing, | |
237 or 'some' for ad hoc linear searches." | |
238 {:deprecated "1.2"} | |
239 [coll x] | |
240 (boolean (some (fn [y] (= y x)) coll))) | |
241 | |
242 | |
243 | |
244 |