9

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).

Wilfred Hughes
  • 29,846
  • 15
  • 139
  • 192
  • possible duplicate of [How to read lines from stdin (\*in\*) in clojure](http://stackoverflow.com/questions/2034059/how-to-read-lines-from-stdin-in-in-clojure) – Shepmaster Dec 29 '13 at 16:13

2 Answers2

12

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.

Community
  • 1
  • 1
JohnJ
  • 4,753
  • 2
  • 28
  • 40
10

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.

d.j.sheldrick
  • 1,430
  • 1
  • 11
  • 16