aboutsummaryrefslogtreecommitdiff
path: root/src/clojure/contrib/monadic_io_streams.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/clojure/contrib/monadic_io_streams.clj')
-rw-r--r--src/clojure/contrib/monadic_io_streams.clj145
1 files changed, 0 insertions, 145 deletions
diff --git a/src/clojure/contrib/monadic_io_streams.clj b/src/clojure/contrib/monadic_io_streams.clj
deleted file mode 100644
index 28772283..00000000
--- a/src/clojure/contrib/monadic_io_streams.clj
+++ /dev/null
@@ -1,145 +0,0 @@
-;; Monadic I/O
-
-;; by Konrad Hinsen
-;; last updated June 24, 2009
-
-;; 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
- #^{:author "Konrad Hinsen"
- :doc "Monadic I/O with Java input/output streams
- Defines monadic I/O statements to be used in a state monad
- with an input or output stream as the state. The macro
- monadic-io creates a stream, runs a monadic I/O statement
- on it, and closes the stream. This structure permits the
- definition of purely functional compound I/O statements
- which are applied to streams that can never escape from the
- monadic statement sequence."}
- clojure.contrib.monadic-io-streams
- (:refer-clojure :exclude (read-line print println flush))
- (:use [clojure.contrib.monads
- :only (with-monad domonad state-m state-m-until)])
- (:use [clojure.contrib.generic.functor :only (fmap)])
- (:use [clojure.contrib.duck-streams :only (reader writer)]))
-
-;
-; Wrap the state into a closure to make sure that "evil" code
-; can't obtain the stream using fetch-state and manipulate it.
-;
-(let [key (Object.)
- lock (fn [state] (fn [x] (if (identical? x key) state nil)))
- unlock (fn [state] (state key))]
-
- ;
- ; Basic stream I/O statements as provided by Java
- ;
- (defn read-char
- "Read a single character"
- []
- (fn [s] [(.read (unlock s)) s]))
-
- (defn read-line
- "Read a single line"
- []
- (fn [s] [(.readLine (unlock s)) s]))
-
- (defn skip-chars
- "Skip n characters"
- [n]
- (fn [s] [(.skip (unlock s) n) s]))
-
- (defn write
- "Write text (a string)"
- [#^String text]
- (fn [s] [(.write (unlock s) text) s]))
-
- (defn flush
- "Flush"
- []
- (fn [s] [(.flush (unlock s)) s]))
-
- (defn print
- "Print obj"
- [obj]
- (fn [s] [(.print (unlock s) obj) s]))
-
- (defn println
- "Print obj followed by a newline"
- ([]
- (fn [s] [(.println (unlock s)) s]))
- ([obj]
- (fn [s] [(.println (unlock s) obj) s])))
-
- ;
- ; Inject I/O streams into monadic I/O statements
- ;
- (defn with-reader
- "Create a reader from reader-spec, run the monadic I/O statement
- on it, and close the reader. reader-spec can be any object accepted
- by clojure.contrib.duck-streams/reader."
- [reader-spec statement]
- (with-open [r (reader reader-spec)]
- (first (statement (lock r)))))
-
- (defn with-writer
- "Create a writer from writer-spec, run the monadic I/O statement
- on it, and close the writer. writer-spec can be any object accepted
- by clojure.contrib.duck-streams/writer."
- [writer-spec statement]
- (with-open [w (writer writer-spec)]
- (first (statement (lock w)))))
-
- (defn with-io-streams
- "Open one or more streams as specified by io-spec, run a monadic
- I/O statement on them, and close the streams. io-spec is
- a binding-like vector in which each stream is specified by
- three element: a keyword by which the stream can be referred to,
- the stream mode (:read or :write), and a stream specification as
- accepted by clojure.contrib.duck-streams/reader (mode :read) or
- clojure.contrib.duck-streams/writer (mode :write). The statement
- is run on a state which is a map from keywords to corresponding
- streams. Single-stream monadic I/O statements must be wrapped
- with clojure.contrib.monads/with-state-field."
- [io-specs statement]
- (letfn [(run-io [io-specs state statement]
- (if (zero? (count io-specs))
- (first (statement state))
- (let [[[key mode stream-spec] & r] io-specs
- opener (cond (= mode :read) reader
- (= mode :write) writer
- :else (throw
- (Exception.
- "Mode must be :read or :write")))]
- (with-open [stream (opener stream-spec)]
- (run-io r (assoc state key (lock stream)) statement)))))]
- (run-io (partition 3 io-specs) {} statement))))
-
-;
-; Compound I/O statements
-;
-(with-monad state-m
-
- (defn- add-line
- "Read one line and add it to the end of the vector lines. Return
- [lines eof], where eof is an end-of-file flag. The input eof argument
- is not used."
- [[lines eof]]
- (domonad
- [line (read-line)]
- (if (nil? line)
- [lines true]
- [(conj lines line) false])))
-
- (defn read-lines
- "Read all lines and return them in a vector"
- []
- (domonad
- [[lines eof] (state-m-until second add-line [[] false])]
- lines)))
-