web-dev-qa-db-ja.com

clojureのstdin(* in *)から行を読み取る方法

私は最初のclojureプログラムを書いていますが、stdinから行を読みたいと思っています。

私がこれを試すとき:

(doall (map #(println %) (line-seq *in*)))

この例外が発生します:

Exception in thread "main" Java.lang.ClassCastException: clojure.lang.LineNumberingPushbackReader cannot be cast to Java.io.BufferedReader (test.clj:0)

バージョン1.0と1.1でも同じ結果が得られます

では、*in*を反復可能なシーケンスに変換するにはどうすればよいですか?これは*in*自体が反復可能であるほど一般的であると思っていたでしょうが、それも機能しません。直接使用しようとすると、次のようになります。

Java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.LineNumberingPushbackReader (NO_SOURCE_FILE:0)

また、clojureで一般的なファイル処理を行う例はありますか?

39
Dave Kirby

ラッピングしてみてください *in*Java.io.BufferedReader。また、devstopfixが指摘しているように、doseqの代わりにdoallを使用します。

(doseq [ln (line-seq (Java.io.BufferedReader. *in*))]
   (println ln))

ご了承ください - line-seq は、ソースとして BufferedReader を必要とすることが文書化されています。

30
seh

doall の代わりに doseq を使用する必要があります。

(doseq [line (line-seq (Java.io.BufferedReader. *in*))] 
    (println line))

doall

Seqの次の連続をウォークスルーし、ヘッドを保持して返します。これにより、seq全体が一度にメモリに常駐します。

doseq

シーケンスの先頭を保持しません。 nilを返します。

22
devstopfix

1行だけを読みたい人のために、 read-line 関数があることに注意してください。

20
Mike Crittenden

適度に小さい入力の場合、以下も機能します。

(let [input-string (Slurp *in*)]
  (println input-string))

または、行で分割します。

(let [lines (clojure.string/split-lines (Slurp *in*))]
  (println lines))
4
mrucci