2011-12-19 15 views
6

私はこの関数を使ってClojureのファイルに書き込みます。Clojureでファイルに書き込む


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

しかし、これは常にこのエラーを生成します。

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

私はここで間違って何をしているのですか?

+0

明快さのために、あなたの質問に関数呼び出しを追加できますか? opqdonutの答えを確認する可能性があります。 – Gert

+0

あなたの質問には答えられませんが、この文脈では興味深いかもしれません:http://stackoverflow.com/questions/7756909/in-clojure-1-3-how-to-read-and-write-a-file/ 7757674#7757674 –

答えて

17

まず第一に、あなたの関数は、多くの入力のためだけで正常に動作:

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 

しかし、あなたは奇妙な何かを渡すしようとしたとき、我々はあなたが記述エラーを取得:このエラー

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

BufferedWriterには複数のオーバーロードされたバージョンwriteがあり、clojureはどちらを呼び出すべきかわからないからです。この場合、矛盾するものはwrite(char[])write(String)です。文字列("a")や整数(1)のような入力では、clojureはメソッドのStringのバージョンを呼び出すことは知っていましたが、他のもの(例えばクロージャーセット#{1})を使用してクロージャーを判断できませんでした。

writelinesへの入力がStringになることを保証するか、str関数を使用して文字列化することはどうですか?

また、spit functionをご覧ください。

+0

注:任意にネストされたClojure値を文字列化する場合は、 'str'ではなく' pr-str'を使用する方が良いでしょう。結果の文字列が直接ストリームに送られる場合は、 'print'または' .write'の後に続く2つの 'pr-str'の代わりに' pr'(または 'prn')を使うべきです。 – raek

0

linesはseqの文字列、ints(chars)またはint配列ではありません。

1

これを試してください:あなたはBufferedWriterのドキュメントを見れば

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

はあなたがwriteを呼んでいた方法への対応方法を見ないだろう(おっと、私は私の愚かな継承されたメソッドを、逃しました!)。 *out*へのバインディングは、デバッグ情報を出力したい場合を除いて、まったく簡単です(この場合、デバッグ情報が少し複雑かもしれません)。