2012-01-06 7 views
2

ファイルを読み取ることができるClojureマクロを作成したい場合、ファイルが正常に読み込まれたときにストリームをクローズする必要があります。このように呼び出されファイルを読み取るClojureマクロ

(import '(java.io FileReader File)) 

(defmacro read([x y] 
`(let ~x 
    (try ~y 
    (. x close) 
    (catch Exception e# e#))))) 

(read [stream (java.io.FileReader (java.io.File "somefile.txt"))] (. stream read))) 

このエラーで結果

java.lang.Exception: No such var: user/x (NO_SOURCE_FILE:8) 

誰もが何か提案を持っています、ありがとう。

+0

入手したエラーメッセージに関する詳細情報はありますか?それはランタイムエラーまたはコンパイル時間ですか? –

+0

@PieterBreed java.lang.Exception:いいえそのような変数:ユーザー/ x(NO_SOURCE_FILE:8) – Silversnail

+0

マクロの4行目で、 "x"は引用符で囲まれていません。 –

答えて

11

明示的にマクロを使用する理由がない限り、with-openをお探しですか?

(defn read [file-name] 
    (with-open [reader (BufferedReader. (FileReader. file-name))] 
    (doseq [line (line-seq reader)] (println line)))) 

ClojureDocs pageによれば、リーダーがフォームの端部で閉じられていることを確実にします。

うまくいけば助けてください!

+0

Isそれは開いていると同様の機能を実行しますか?あるいは、何か劇的に違うことをしたいのですか?もしそれが同じになるのであれば、私がリンクしているClojureDocsのページに、そのソースを読む価値があります。 – toofarsideways

1

はい、と私は引用場合は "〜X" この例外は'~x"は今[stream (FileReader. (File. "somefile.txt"))]を参照するためです

<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: close for class clojure.lang.PersistentVector> 

がスローされます。あなたが得ているエラーは理にかなっています。マクロは、上記のベクトルのclose()を呼び出そうとするコードを吐き出します。 (first ~x)を使用して試すことができます。

このマクロは非常に一般的であり、ユーザーが書き込むコード量を大幅に削減しないことに注意してください。あなたは(これはおそらく動作しません)これらの線に沿って何かを試みることができる

(import '(java.io FileReader File)) 

(defmacro read([fname] 
`(try 
    (let [stream# (FileReader. (File. ~fname)) 
     rtnval (. stream# read)] 
    (do 
     (. stream# close) 
     rtnval)) 
    (catch Exception e# e#))) 

しかし、私はわずか50%のように私の答えは、どんな意味があります確信しています。

関連する問題