Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read all lines from stdin in Clojure

I'm writing a Brainf*** interpreter in Clojure. I want to pass a program in using stdin. However, I still need to read from stdin later for user input.

Currently, I'm doing this:

$ cat sample_programs/hello_world.bf | lein trampoline run

My Clojure code is only reading the first line though, using read-line:

(defn -main
  "Read a BF program from stdin and evaluate it."
  []
  ;; FIXME: only reads the first line from stdin
  (eval-program (read-line)))

How can I read all the lines in the file I've piped in? *in* seems to be an instance of java.io.Reader, but that only provides .read (one char), .readLine (one line) and read(char[] cbuf, int off, int len) (seems very low level).

like image 652
Wilfred Hughes Avatar asked Dec 29 '13 13:12

Wilfred Hughes


2 Answers

It's simple enough to read all input data as a single string:

(defn -main []
  (let [in (slurp *in*)]
    (println in)))

This works fine if your file can fit in available memory; for reading large files lazily, see this answer.

like image 198
JohnJ Avatar answered Nov 18 '22 07:11

JohnJ


you could get a lazy seq of lines from *in* like this:

(take-while identity (repeatedly #(.readLine *in*)))

or this:

(line-seq (java.io.BufferedReader. *in*))

which are functionally identical.

like image 10
d.j.sheldrick Avatar answered Nov 18 '22 07:11

d.j.sheldrick