Por favor, no use anidados de Def. No funciona, lo que piensas que hace. def es siempre global! Para los lugareños, use let en su lugar. Si bien las funciones de la biblioteca son agradables de conocer, aquí hay una versión que orquesta algunas características de la programación funcional en general y clojure en particular.
(import 'java.io.FileWriter 'java.io.FileReader 'java.io.BufferedReader)
(defn translate-coords
Las cadenas de documentos se pueden consultar en el REPL a través de (doc translate-coords). Funciona eg. para todas las funciones básicas. Así que el suministro de uno es una buena idea.
"Reads coordinates from infile, translates them with the given
translator and writes the result to outfile."
traductor es una función (quizás anónima) que extrae la traducción de la plantilla repetitiva circundante. Entonces podemos reutilizar estas funciones con diferentes reglas de transformación. Las sugerencias de tipo aquí evitan la reflexión para los constructores.
[translator #^String infile #^String outfile]
Abra los archivos. with-open se ocupará de que los archivos se cierren cuando se deja su cuerpo. Ya sea a través de un "drop off the bottom" normal o sea a través de una excepción lanzada.
(with-open [in (BufferedReader. (FileReader. infile))
out (FileWriter. outfile)]
ligamos la corriente *out*
temporalmente al archivo de salida. De modo que cualquier impresión dentro del enlace se imprimirá en el archivo.
(binding [*out* out]
Los medios map
: tomar la SEC y aplicar la función dada a cada elemento y devolver la SEC de los resultados. El #()
es una notación abreviada para una función anónima. Se necesita un argumento, que se rellena en el %
. El doseq
es básicamente un bucle sobre la entrada. Como hacemos eso para los efectos secundarios (es decir, para imprimir en un archivo), doseq
es la construcción correcta. Regla de oro: map
: lazy => para el resultado, doseq
: ansioso => por efectos secundarios.
(doseq [coords (map #(.split % ",") (line-seq in))]
println
se encarga de la \n
al final de la línea. interpose
toma la secuencia y agrega el primer argumento (en nuestro caso "") entre sus elementos. (apply str [1 2 3])
es equivalente a (str 1 2 3)
y es útil para construir llamadas a funciones dinámicamente. El ->>
es una macro relativamente nueva en clojure, que ayuda un poco con la legibilidad. Significa "tomar el primer argumento y agregarlo como último elemento a la llamada de función". El dado ->>
es equivalente a: (println (apply str (interpose " " (translator coords))))
. (Edit: Otra nota: dado que el separador es \space
, que podría aquí escriben igual de bien (apply println (translator coords))
, pero la versión interpose
permite parametrizar también el separador como lo hicimos con la función de traductor, mientras que la versión corta sería cablear \space
.)
(->> (translator coords)
(interpose " ")
(apply str)
println)))))
(defn survey->cartography-format
"Translate coords in survey format to cartography format."
Aquí utilizamos desestructuración (observe el doble [[]]
). Significa que el argumento para la función es algo que se puede convertir en una secuencia, por ejemplo. un vector o una lista. Enlace el primer elemento a y
, el segundo a x
y así sucesivamente.
[[y x z p]]
[p x y z])
(translate-coords survey->cartography-format "survey_coords.txt" "cartography_coords.txt")
Una vez más menos entrecortado:
(import 'java.io.FileWriter 'java.io.FileReader 'java.io.BufferedReader)
(defn translate-coords
"Reads coordinates from infile, translates them with the given
translator and writes the result to outfile."
[translator #^String infile #^String outfile]
(with-open [in (BufferedReader. (FileReader. infile))
out (FileWriter. outfile)]
(binding [*out* out]
(doseq [coords (map #(.split % ",") (line-seq in))]
(->> (translator coords)
(interpose " ")
(apply str)
println)))))
(defn survey->cartography-format
"Translate coords in survey format to cartography format."
[[y x z p]]
[p x y z])
(translate-coords survey->cartography-format "survey_coords.txt" "cartography_coords.txt")
Espero que esto ayude.
Editar: Para la lectura de CSV, probablemente quieras algo como OpenCSV.
'mi ($ x, $ y, $ z, $ p) = dividir /, /;' –
Buen punto - TIMTOWTDI. Gracias. –