diff options
Diffstat (limited to 'src/clojure/contrib/monadic_io_streams.clj')
-rw-r--r-- | src/clojure/contrib/monadic_io_streams.clj | 145 |
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))) - |