As the follow up to my post Running Clojure shell scripts in *nix enviornments, here is how I implemented an example using futures to parse lines read in from standard in as if the input was piped from a tail and writing out the result of parsing the line to standard out.
First due to wanting to run this a script from the command line I add this a the first line of the script:
!/usr/bin/env lein exec
As well, I will also be wanting to use the join function from the clojure.string namespace.
(use '[clojure.string :only (join)])
When dealing with futures I knew I would need an agent to adapt standard out.
(def out (agent *out*))
I also wanted to separate each line by a new line so I created a function writeln. The function takes a Java Writer and calls write and flush on each line passed in to the function:
(defn writeln [^java.io.Writer w line]
(doto w
(.write (str line "n"))
.flush))
Next I have my function to analyze the line, as well as sending the result of that function to the agent via the send-off function.
(defn analyze-line [line] (str line " " (join " " (map #(join ":" %) (sort-by val > (frequencies line)))))) (defn process-line [line] (send-off out writeln (analyze-line line)))
The analyze-line function is just some sample code to return a string of the line and the frequencies of each character in the line passed in. The process-line function takes a line and calls send-off to the agent out for the function writeln with the results of calling the function analyze-line.
With all of these functions defined I now need to just loop continuously and process lines that are not empty, and call process-line for each line as a future.
(loop []
(let [line (read-line)]
(when line
(future (process-line line)))
(recur)))