diff options
author | Konrad Hinsen <konrad.hinsen@laposte.net> | 2009-02-23 12:43:07 +0000 |
---|---|---|
committer | Konrad Hinsen <konrad.hinsen@laposte.net> | 2009-02-23 12:43:07 +0000 |
commit | fabb7df259390e9eaafc1023240b0cfce95941c2 (patch) | |
tree | 2679bde4338237b347cc84a9ecb88282e533b383 /src/clojure/contrib/stream-utils.clj | |
parent | 6a59026ea72fcd1ec1d0465326d97e23ed37e4cd (diff) |
stream-utils: fixed file name
Diffstat (limited to 'src/clojure/contrib/stream-utils.clj')
-rw-r--r-- | src/clojure/contrib/stream-utils.clj | 180 |
1 files changed, 0 insertions, 180 deletions
diff --git a/src/clojure/contrib/stream-utils.clj b/src/clojure/contrib/stream-utils.clj deleted file mode 100644 index fd4e6a04..00000000 --- a/src/clojure/contrib/stream-utils.clj +++ /dev/null @@ -1,180 +0,0 @@ -;; Stream utilities - -;; by Konrad Hinsen -;; last updated January 25, 2009 - -;; Note: this module is at least as experimental as Clojure's stream -;; facilities. It may change significantly, change name, or disappear -;; in the future. Don't rely on it for your applications. I put this -;; module in clojure.contrib so that it can serve as a testground and -;; a basis for discussions ont the group. - -;; Copyright (c) Konrad Hinsen, 2009. All rights reserved. The use -;; and distribution terms for this software are covered by the Eclipse -;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) -;; which can be found in the file epl-v10.html at the root of this -;; distribution. By using this software in any fashion, you are -;; agreeing to be bound by the terms of this license. You must not -;; remove this notice, or any other, from this software. - -(ns clojure.contrib.stream-utils - (:use [clojure.contrib.monads])) - -;; Streams - -; Stream of integers -(defn int-stream - "Return a stream of integers starting from init and incrementing by step - until end, the first value not returned. The defaults are 0, 1, and nil, - where nil stands for an infinite stream." - ([] (int-stream 0 1 nil)) - ([init] (int-stream init 1 nil)) - ([init step] (int-stream init step nil)) - ([init step end] - (let [n (into-array [init])] - (stream - (fn [eos] - (let [current (aget n 0)] - (if (or (nil? end) (< current end)) - (do - (aset n 0 (+ current step)) - current) - eos))))))) - -;; Stream transformers - -(defn drop-first - "Return a stream that returns the elements of s except for the first n ones." - [n s] - (let [eos (Object.) - iter (stream-iter s) - gen (fn [eos] (next! iter eos))] - (doseq [_ (range n)] (gen eos)) - (stream gen))) - -;; Monadic stream transformers - -; Generator monad -; -; This monad represents computations with generators, as defined for -; Clojure streams: a function of one argument, an end-of-stream value, -; that returns at each call the "next" value of the stream, until the -; end of the stream is reached, and from then on it returns the supplied -; eos value forever. This monad permits the simple composition of such -; generators. -; -; The use of generators instead of streams as the basis of this monad -; has two reasons: -; 1) It is not possible to pass around a stream such that each -; monadic computation step takes one item of it, because there can -; be only one iterator per stream. -; 2) One could use iterators instead of generators as the monadic -; values, even with minimal changes, but each computational step -; in the monad would then create a new stream and a new iter, -; adding overhead for no apparent benefit. - -(defmonad generator - "Monad describing stream-transforming computations. The monadic - values are generator functions." - [m-result (fn m-result-generator [v] - (fn [eos] v)) - m-bind (fn m-bind-generator [mv f] - (fn [eos] - (let [v (mv eos)] - (if (identical? v eos) - eos - ((f v) eos))))) - ]) - -; A macro for defining stream transformers using the generator monad. -; It wraps the input streams into iters-that-look-like-generators, -; and converts the resulting generator into a stream. -(defmacro stream-transformer - [stream-args & body] - `(stream (let [~stream-args (map stream-iter ~stream-args)] - (with-monad generator ~@body)))) - - -; Derive a variant of the generator monad that permits the -; use of :when conditions. Invalid values in the output are -; represented by ::skip, which is filtered out in the end -; by applying remove-skip. The macro stream-transformer-cond -; takes care of all these administrative details. -(def generator-cond (maybe-t generator ::skip :m-plus-from-maybe)) - -(defn remove-skip [g] - (fn [eos] - (loop [v (g eos)] - (if (identical? v ::skip) - (recur (g eos)) - v)))) - -(defmacro stream-transformer-cond - [stream-args & body] - `(stream (remove-skip - (let [~stream-args (map stream-iter ~stream-args)] - (with-monad generator-cond ~@body))))) - - -;; Some examples of monadic stream transformers - -(defn skip-s [s] - "Return a stream that skips every second item of s" - (stream-transformer [s] - (domonad - [x1 s - x2 s] - x2))) - -(defn partition-s [n s] - "Return a stream in which each element is a sequence of n consecutive - elements of the input stream s." - (stream-transformer [s] - (m-seq (replicate n s)))) - -; Map a function on streams. -; Map has to be defined by an explicit expression for every number of -; arguments because the m-lift macro requires a constant as its first -; argument. -(defn map-s - "Return a stream of the results of applying f on one item of each - input sequence." - ([f s] - (stream-transformer [s] - ((m-lift 1 f) s))) - ([f s1 s2] - (stream-transformer [s1 s2] - ((m-lift 2 f) s1 s2))) - ([f s1 s2 s3] - (stream-transformer [s1 s2 s3] - ((m-lift 3 f) s1 s2 s3))) - ([f s1 s2 s3 s4] - (stream-transformer [s1 s2 s3 s4] - ((m-lift 4 f) s1 s2 s3 s4))) - ([f s1 s2 s3 s4 s5] - (stream-transformer [s1 s2 s3 s4 s5] - ((m-lift 5 f) s1 s2 s3 s4 s5)))) - -(defn filter-s [p s] - "Return a stream consisting of the elements of s that satisfy predicate p." - (stream-transformer-cond [s] - (domonad - [x s :when (p x)] - x))) - -(comment - -; Some example expressions - -(take 10 (drop-first 5 (int-stream))) - -(take 10 (skip-s (int-stream))) - -(take 10 (partition-s 3 (int-stream))) - -(take 10 (map-s inc (int-stream))) -(take 10 (map-s + (int-stream) (map-s inc (int-stream)))) - -(take 10 (filter-s #(zero? (rem % 3)) (int-stream))) - -)
\ No newline at end of file |