Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing a lazy, functional, interactive command line application in Clojure

I'm wondering: what is the best way to write a Clojure program that interacts with a user or another program thorough stdin and stdout?

Clearly it would be possible to write some kind of imperative loop, but I'm hoping to find something more lazy / functional, a bit inspired by Haskell's "interact" function.

like image 777
mikera Avatar asked Mar 30 '11 12:03

mikera


1 Answers

This was the best I could come up with:

(defn interact [f]
  (lazy-seq 
    (cons (do (let [input (read-line)
                    result (f input)]
                (println result)
                {:input input :result result}))
          (interact f))))

You could use it like this:

(def session
  (take-while #(not= (:result %) 0)
              (interact count)))

REPL:

user=> (str "Total Length: " (reduce #(+ %1 (:result %2)) 0 session))
foobar
6
stackoverflow
13

0
"Total Length: 19"
user=> session
({:input "foobar", :result 6} {:input "stackoverflow", :result 13})
like image 62
dbyrne Avatar answered Oct 13 '22 23:10

dbyrne