aboutsummaryrefslogtreecommitdiff
path: root/src/clojure/contrib/stream-utils.clj
diff options
context:
space:
mode:
authorKonrad Hinsen <konrad.hinsen@laposte.net>2009-02-23 12:43:07 +0000
committerKonrad Hinsen <konrad.hinsen@laposte.net>2009-02-23 12:43:07 +0000
commitfabb7df259390e9eaafc1023240b0cfce95941c2 (patch)
tree2679bde4338237b347cc84a9ecb88282e533b383 /src/clojure/contrib/stream-utils.clj
parent6a59026ea72fcd1ec1d0465326d97e23ed37e4cd (diff)
stream-utils: fixed file name
Diffstat (limited to 'src/clojure/contrib/stream-utils.clj')
-rw-r--r--src/clojure/contrib/stream-utils.clj180
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