Как читать строки из stdin (* in *) в ближайшем будущем - PullRequest
33 голосов
/ 09 января 2010

Я пишу свою первую программу 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?

Ответы [ 4 ]

26 голосов
/ 09 января 2010

Попробуйте обернуть *in* в java.io.BufferedReader. А также используйте doseq вместо doall, как указало devstopfix:

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

Обратите внимание, что для line-seq задокументировано, что в качестве источника требуется BufferedReader.

21 голосов
/ 26 января 2011

Вы, вероятно, должны использовать дозаq вместо doall :

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

DOALL

Пройдет по последовательным последовательностям seq, удерживает голову и возвращает ее, в результате чего весь seq остается в памяти одновременно.

doseq

Не сохраняет заголовок последовательности. Возвращает ноль.

20 голосов
/ 22 декабря 2011

Просто обратите внимание, что для тех, кто хочет читать только одну строку, есть функция read-line .

4 голосов
/ 05 марта 2018

Для относительно небольших входных данных также будет работать следующее:

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

Или, разделив по строкам:

(let [lines (clojure.string/split-lines (slurp *in*))]
  (println lines))
...