2012-01-06 27 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

你能提供更多关于你所得到的错误信息的信息吗?它是运行时错误还是编译时间? – 2012-01-06 12:08:24

+0

@PieterBreed java.lang.Exception:没有这样的var:user/x(NO_SOURCE_FILE:8) – Silversnail 2012-01-06 13:37:20

+0

在宏的第4行,“x”不是没有引号的。这仍然有很多错误... – 2012-01-06 14:20:10

回答

11

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

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

根据该ClojureDocs page,它确保读者在表单的结束时关闭。

希望有帮助!

+0

它执行类似的功能,以打开?或者你想做一些完全不同的事情?如果它将会是相同的,那么阅读源代码可能是值得的,我链接到的ClojureDocs页面包含函数的源代码,如果你想阅读它的话...... – toofarsideways 2012-01-06 12:27:26

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%肯定我的回答让任何意义。