Mercurial > lasercutter
diff src/clojure/contrib/seq.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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojure/contrib/seq.clj Sat Aug 21 06:25:44 2010 -0400 1.3 @@ -0,0 +1,238 @@ 1.4 +;;; seq_utils.clj -- Sequence utilities for Clojure 1.5 + 1.6 +;; by Stuart Sierra, http://stuartsierra.com/ 1.7 +;; last updated March 2, 2009 1.8 + 1.9 +;; Copyright (c) Stuart Sierra, 2008. All rights reserved. The use 1.10 +;; and distribution terms for this software are covered by the Eclipse 1.11 +;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 1.12 +;; which can be found in the file epl-v10.html at the root of this 1.13 +;; distribution. By using this software in any fashion, you are 1.14 +;; agreeing to be bound by the terms of this license. You must not 1.15 +;; remove this notice, or any other, from this software. 1.16 + 1.17 + 1.18 +;; Change Log 1.19 +;; 1.20 +;; January 10, 2009 (Stuart Sierra): 1.21 +;; 1.22 +;; * BREAKING CHANGE: "includes?" now takes collection as first 1.23 +;; argument. This is more consistent with Clojure collection 1.24 +;; functions; see discussion at http://groups.google.com/group/clojure/browse_thread/thread/8b2c8dc96b39ddd7/a8866d34b601ff43 1.25 + 1.26 + 1.27 +(ns 1.28 + ^{:author "Stuart Sierra (and others)", 1.29 + :doc "Sequence utilities for Clojure"} 1.30 + clojure.contrib.seq 1.31 + (:import (java.util.concurrent LinkedBlockingQueue TimeUnit) 1.32 + (java.lang.ref WeakReference)) 1.33 + (:refer-clojure :exclude [frequencies shuffle partition-by reductions partition-all group-by flatten])) 1.34 + 1.35 + 1.36 +;; 'flatten' written by Rich Hickey, 1.37 +;; see http://groups.google.com/group/clojure/msg/385098fabfcaad9b 1.38 +(defn flatten 1.39 + "DEPRECATED. Prefer clojure.core version. 1.40 + Takes any nested combination of sequential things (lists, vectors, 1.41 + etc.) and returns their contents as a single, flat sequence. 1.42 + (flatten nil) returns nil." 1.43 + {:deprecated "1.2"} 1.44 + [x] 1.45 + (filter (complement sequential?) 1.46 + (rest (tree-seq sequential? seq x)))) 1.47 + 1.48 +(defn separate 1.49 + "Returns a vector: 1.50 + [ (filter f s), (filter (complement f) s) ]" 1.51 + [f s] 1.52 + [(filter f s) (filter (complement f) s)]) 1.53 + 1.54 +(defn indexed 1.55 + "Returns a lazy sequence of [index, item] pairs, where items come 1.56 + from 's' and indexes count up from zero. 1.57 + 1.58 + (indexed '(a b c d)) => ([0 a] [1 b] [2 c] [3 d])" 1.59 + [s] 1.60 + (map vector (iterate inc 0) s)) 1.61 + 1.62 +;; group-by written by Rich Hickey; 1.63 +;; see http://paste.lisp.org/display/64190 1.64 +(defn group-by 1.65 + "DEPRECATED. Prefer clojure.core version. 1.66 + Returns a sorted map of the elements of coll keyed by the result of 1.67 + f on each element. The value at each key will be a vector of the 1.68 + corresponding elements, in the order they appeared in coll." 1.69 + {:deprecated "1.2"} 1.70 + [f coll] 1.71 + (reduce 1.72 + (fn [ret x] 1.73 + (let [k (f x)] 1.74 + (assoc ret k (conj (get ret k []) x)))) 1.75 + (sorted-map) coll)) 1.76 + 1.77 +;; partition-by originally written by Rich Hickey; 1.78 +;; modified by Stuart Sierra 1.79 +(defn partition-by 1.80 + "DEPRECATED. Prefer clojure.core version. 1.81 + Applies f to each value in coll, splitting it each time f returns 1.82 + a new value. Returns a lazy seq of lazy seqs." 1.83 + {:deprecated "1.2"} 1.84 + [f coll] 1.85 + (when-let [s (seq coll)] 1.86 + (let [fst (first s) 1.87 + fv (f fst) 1.88 + run (cons fst (take-while #(= fv (f %)) (rest s)))] 1.89 + (lazy-seq 1.90 + (cons run (partition-by f (drop (count run) s))))))) 1.91 + 1.92 +(defn frequencies 1.93 + "DEPRECATED. Prefer clojure.core version. 1.94 + Returns a map from distinct items in coll to the number of times 1.95 + they appear." 1.96 + {:deprecated "1.2"} 1.97 + [coll] 1.98 + (reduce (fn [counts x] 1.99 + (assoc counts x (inc (get counts x 0)))) 1.100 + {} coll)) 1.101 + 1.102 +;; recursive sequence helpers by Christophe Grand 1.103 +;; see http://clj-me.blogspot.com/2009/01/recursive-seqs.html 1.104 +(defmacro rec-seq 1.105 + "Similar to lazy-seq but binds the resulting seq to the supplied 1.106 + binding-name, allowing for recursive expressions." 1.107 + [binding-name & body] 1.108 + `(let [s# (atom nil)] 1.109 + (reset! s# (lazy-seq (let [~binding-name @s#] ~@body))))) 1.110 + 1.111 +(defmacro rec-cat 1.112 + "Similar to lazy-cat but binds the resulting sequence to the supplied 1.113 + binding-name, allowing for recursive expressions." 1.114 + [binding-name & exprs] 1.115 + `(rec-seq ~binding-name (lazy-cat ~@exprs))) 1.116 + 1.117 + 1.118 +;; reductions by Chris Houser 1.119 +;; see http://groups.google.com/group/clojure/browse_thread/thread/3edf6e82617e18e0/58d9e319ad92aa5f?#58d9e319ad92aa5f 1.120 +(defn reductions 1.121 + "DEPRECATED. Prefer clojure.core version. 1.122 + Returns a lazy seq of the intermediate values of the reduction (as 1.123 + per reduce) of coll by f, starting with init." 1.124 + {:deprecated "1.2"} 1.125 + ([f coll] 1.126 + (if (seq coll) 1.127 + (rec-seq self (cons (first coll) (map f self (rest coll)))) 1.128 + (cons (f) nil))) 1.129 + ([f init coll] 1.130 + (rec-seq self (cons init (map f self coll))))) 1.131 + 1.132 +(defn rotations 1.133 + "Returns a lazy seq of all rotations of a seq" 1.134 + [x] 1.135 + (if (seq x) 1.136 + (map 1.137 + (fn [n _] 1.138 + (lazy-cat (drop n x) (take n x))) 1.139 + (iterate inc 0) x) 1.140 + (list nil))) 1.141 + 1.142 +(defn partition-all 1.143 + "DEPRECATED. Prefer clojure.core version. 1.144 + Returns a lazy sequence of lists like clojure.core/partition, but may 1.145 + include lists with fewer than n items at the end." 1.146 + {:deprecated "1.2"} 1.147 + ([n coll] 1.148 + (partition-all n n coll)) 1.149 + ([n step coll] 1.150 + (lazy-seq 1.151 + (when-let [s (seq coll)] 1.152 + (cons (take n s) (partition-all n step (drop step s))))))) 1.153 + 1.154 +(defn shuffle 1.155 + "DEPRECATED. Prefer clojure.core version. 1.156 + Return a random permutation of coll" 1.157 + {:deprecated "1.2"} 1.158 + [coll] 1.159 + (let [l (java.util.ArrayList. coll)] 1.160 + (java.util.Collections/shuffle l) 1.161 + (seq l))) 1.162 + 1.163 +(defn rand-elt 1.164 + "DEPRECATED. Prefer clojure.core/rand-nth. 1.165 + Return a random element of this seq" 1.166 + {:deprecated "1.2"} 1.167 + [s] 1.168 + (nth s (rand-int (count s)))) 1.169 + 1.170 +;; seq-on written by Konrad Hinsen 1.171 +(defmulti seq-on 1.172 + "Returns a seq on the object s. Works like the built-in seq but as 1.173 + a multimethod that can have implementations for new classes and types." 1.174 + {:arglists '([s])} 1.175 + type) 1.176 + 1.177 +(defmethod seq-on :default 1.178 + [s] 1.179 + (seq s)) 1.180 + 1.181 + 1.182 +(defn find-first 1.183 + "Returns the first item of coll for which (pred item) returns logical true. 1.184 + Consumes sequences up to the first match, will consume the entire sequence 1.185 + and return nil if no match is found." 1.186 + [pred coll] 1.187 + (first (filter pred coll))) 1.188 + 1.189 +; based on work related to Rich Hickey's seque. 1.190 +; blame Chouser for anything broken or ugly. 1.191 +(defn fill-queue 1.192 + "filler-func will be called in another thread with a single arg 1.193 + 'fill'. filler-func may call fill repeatedly with one arg each 1.194 + time which will be pushed onto a queue, blocking if needed until 1.195 + this is possible. fill-queue will return a lazy seq of the values 1.196 + filler-func has pushed onto the queue, blocking if needed until each 1.197 + next element becomes available. filler-func's return value is ignored." 1.198 + ([filler-func & optseq] 1.199 + (let [opts (apply array-map optseq) 1.200 + apoll (:alive-poll opts 1) 1.201 + q (LinkedBlockingQueue. (:queue-size opts 1)) 1.202 + NIL (Object.) ;nil sentinel since LBQ doesn't support nils 1.203 + weak-target (Object.) 1.204 + alive? (WeakReference. weak-target) 1.205 + fill (fn fill [x] 1.206 + (if (.get alive?) 1.207 + (if (.offer q (if (nil? x) NIL x) apoll TimeUnit/SECONDS) 1.208 + x 1.209 + (recur x)) 1.210 + (throw (Exception. "abandoned")))) 1.211 + f (future 1.212 + (try 1.213 + (filler-func fill) 1.214 + (finally 1.215 + (.put q q))) ;q itself is eos sentinel 1.216 + nil)] ; set future's value to nil 1.217 + ((fn drain [] 1.218 + weak-target ; force closing over this object 1.219 + (lazy-seq 1.220 + (let [x (.take q)] 1.221 + (if (identical? x q) 1.222 + @f ;will be nil, touch just to propagate errors 1.223 + (cons (if (identical? x NIL) nil x) 1.224 + (drain)))))))))) 1.225 + 1.226 +(defn positions 1.227 + "Returns a lazy sequence containing the positions at which pred 1.228 + is true for items in coll." 1.229 + [pred coll] 1.230 + (for [[idx elt] (indexed coll) :when (pred elt)] idx)) 1.231 + 1.232 +(defn includes? 1.233 + "Returns true if coll contains something equal (with =) to x, 1.234 + in linear time. Deprecated. Prefer 'contains?' for key testing, 1.235 + or 'some' for ad hoc linear searches." 1.236 + {:deprecated "1.2"} 1.237 + [coll x] 1.238 + (boolean (some (fn [y] (= y x)) coll))) 1.239 + 1.240 + 1.241 +