2012-01-06 66 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%肯定我的回答讓任何意義。