2011-12-19 19 views
6

Estoy usando esta función para escribir en un archivo en Clojure.Escribir en un archivo en Clojure


(defn writelines [file-path lines] 
    (with-open [wtr (clojure.java.io/writer file-path)] 
    (doseq [line lines] (.write wtr line)))) 

Pero esto siempre genera este error:

IllegalArgumentException No matching method found: write for 
class java.io.BufferedWriter in 
clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:79) 

¿qué estoy haciendo mal aquí?

+0

¿Podría usted, para mayor claridad, agregar una llamada a función de ejemplo en su pregunta? Es probable que confirme la respuesta de Opqdonut. – Gert

+0

No es una respuesta a tu pregunta, pero podría ser interesante en este contexto: http://stackoverflow.com/questions/7756909/in-clojure-1-3-how-to-read-and-write-a-file/ 7757674 # 7757674 –

Respuesta

17

En primer lugar, su función funciona bien para muchas entradas:

Clojure 1.3.0 
user=> (defn writelines [file-path lines] 
    (with-open [wtr (clojure.java.io/writer file-path)] 
    (doseq [line lines] (.write wtr line)))) 
#'user/writelines 
user=> (writelines "foobar" ["a" "b"]) 
nil 
user=> (writelines "quux" [1 2]) 
nil 

Sin embargo, cuando se intenta pasar de algo extraño que sale el error que describimos:

user=> (writelines "quux" [#{1}]) 
IllegalArgumentException No matching method found: write for class java.io.BufferedWriter clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:79) 

Este error es porque BufferedWriter tiene múltiples versiones sobrecargadas de write y clojure no sabe a cuál llamar. En este caso, los conflictivos son write(char[]) y write(String). Con entradas como strings ("a") y enteros (1), clojure supo llamar a la versión String del método, pero con algo más (por ejemplo, un conjunto de clojure, #{1}) no pudo decidir clojure.

¿Qué tal si nos aseguramos de que las entradas a writelines son de hecho String o las entallan usando la función str?

Además, eche un vistazo a spit function.

+0

Nota: Si desea stringify un valor Clojure anidado arbitrariamente, es mejor usar 'pr-str' en lugar de' str'. Si la cadena resultante se alimenta directamente a una secuencia, debe usar 'pr' (o' prn') en lugar de 'pr-str' de dos pasos seguido de' print' o '.write'. – raek

0

Pasando por el mensaje de excepción, lines no es un conjunto de cadenas, ints (chars) o int arrays.

1

Prueba esto:

(defn writelines [file-path lines] 
    (with-open [wtr (clojure.java.io/writer file-path)] 
    (binding [*out* wtr] 
     (doseq [line lines] (print wtr line))))) 

Si nos fijamos en la documentación de BufferedWriter verás ningún método correspondiente a la forma en que estuviera llamando write (gritos, echaba de menos los métodos heredados, tonto de mí!). En mi opinión, enlazar a *out* es más fácil, a menos que también desee generar información de depuración, en cuyo caso podría ser un poco más complicado.