2010-01-09 21 views
28

Escribo mi primer programa clojure y quiero leer líneas de stdin.Cómo leer líneas de stdin (* en *) en clojure

Cuando intento esto:

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

consigo esta excepción:

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

puedo obtener los mismos resultados en la versión 1.0 y 1.1

Entonces, ¿cómo puedo convertir *in* en una seq puedo repetir? Yo hubiera pensado que esto es bastante común que *in* sí sería iterable, pero que no funciona bien - si trato de usarlo directamente me sale:

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

Además, ¿hay algún ejemplo de hacer archivo general manejo en clojure?

+2

reemplazando (mapa # (println%) (línea-ss ..)) con just (map println (line-seq ..)) podría ser agradable – GabiMe

Respuesta

25

trate de envolver *in* en un java.io.BufferedReader. Y también utilizar en lugar de doseqdoall, como devstopfix señaló:

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

Tenga en cuenta que line-seq se documenta a requerir una BufferedReader como su fuente.

+0

Gracias, eso lo solucionó. –

+2

Este código no funciona. Me sale el error "doseq requiere un vector para su enlace" Try was @devstopfix escribió. Funcionó para mí. – Jason

+1

@Jason Utilice dorun en lugar de doseq para este formulario. doseq requiere una forma de enlace. dorun obliga a un seq perezoso. – user1009908

19

Probablemente debería utilizar doseq en lugar de doall:

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

doall:

entra por la nexts sucesivas de la SEC, conserva la cabeza y lo devuelve, lo que provoca toda la SEQ para residir en la memoria a la vez.

doseq:

no conserva la cabeza de la secuencia. Devuelve nil.

17

Solo una nota que para cualquiera que quiera leer solo una línea, existe la función read-line.

0

Para las entradas razonablemente pequeños, el siguiente también funcionaría:

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

O, división por líneas:

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