2010-01-09 8 views
28

Ich schreibe mein erstes Clojure-Programm und möchte Zeilen von Stdin lesen.So lesen Sie Zeilen von stdin (* in *) in clojure

Wenn ich das versuchen:

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

Ich erhalte diese Ausnahme:

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

Ich erhalte die gleichen Ergebnisse in der Version 1.0 und 1.1

So wie ich *in* in eine umwandeln Seq kann ich über iterieren? Ich hätte gedacht, dass diese häufig genug ist, dass *in* selbst wäre iterable, aber das funktioniert auch nicht - wenn ich versuche, es zu verwenden, um direkt die ich erhalten:

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

Auch gibt es Beispiele für tun allgemeine Datei Handhabung in clojure?

+2

ersetzen (Karte # (println%) (line-Seq ..)) mit nur (map println (line-seq ..)) könnte nett sein – GabiMe

Antwort

25

Versuchen Sie, *in* in einem java.io.BufferedReader zu wickeln. Und verwenden Sie auch doseq statt doall, wie devstopfix wies darauf hin:

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

Beachten Sie, dass line-seq dokumentiert eine BufferedReader als seine Quelle zu verlangen.

+0

Danke, das hat es behoben. –

+2

Dieser Code funktioniert nicht. Ich bekomme den Fehler "doseq benötigt einen Vektor für seine Bindung" Versuch war @devstopfix hat geschrieben. Es hat von mir funktioniert. – Jason

+1

@Jason Verwenden Sie Dorun anstelle von doseq für dieses Formular. doseq benötigt eine verbindliche Form. Dorun zwingt einen faulen Seq. – user1009908

19

Sie sollten wahrscheinlich doseq anstelle von doall:

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

doall:

Spaziergänge durch die aufeinanderfolgenden nexts des seq, behält den Kopf und gibt ihn zurück, so dass die gesamte Seq was bewirkt, daß gleichzeitig im Speicher vorhanden sein.

doseq:

Ist der Kopf der Sequenz nicht behalten. Gibt null zurück.

17

Nur eine Anmerkung, dass für jemanden, der nur eine einzelne Zeile lesen möchte, gibt es die read-line Funktion.

0

Für einigermaßen kleine Eingänge, arbeiten die folgenden würde auch:

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

Oder Spaltung durch Linien:

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