Clojure宏读取文件

时间:2012-01-06 11:54:45

标签: macros 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) 

有人有任何建议,谢谢。

2 个答案:

答案 0 :(得分:11)

您是否在寻找with-open,除非有某些原因您想明确使用宏?

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

根据ClojureDocs page,它确保在表单末尾关闭阅读器。

希望这有帮助!

答案 1 :(得分:1)

  

是的,如果我引用“~x”,则抛出此异常

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

这是因为'~x"现在指的是[stream (FileReader. (File. "somefile.txt"))]。你得到的错误是有道理的。宏吐出代码,试图在上面的向量上调用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%肯定我的回答才有意义。