view 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
line wrap: on
line source
1 ;;; seq_utils.clj -- Sequence utilities for Clojure
3 ;; by Stuart Sierra, http://stuartsierra.com/
4 ;; last updated March 2, 2009
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.
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 ;;
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]))
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))))
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)])
55 (defn indexed
56 "Returns a lazy sequence of [index, item] pairs, where items come
57 from 's' and indexes count up from zero.
59 (indexed '(a b c d)) => ([0 a] [1 b] [2 c] [3 d])"
60 [s]
61 (map vector (iterate inc 0) s))
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))
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)))))))
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))
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)))))
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)))
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)))))
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)))
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)))))))
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)))
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))))
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)
179 (defmethod seq-on :default
180 [s]
181 (seq s))
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)))
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))))))))))
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))
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)))