2011-08-26 45 views
3

懶惰的字符串錯誤,我打算檢索一個大的網頁,並嘗試這種在Clojure的Web檢索到的Clojure

(defn fetch-url [url] 
    "Retrieves the web page specified by the url." 
    (with-open [the-stream (.openStream (java.net.URL. url))] 
    (let [reader (new BufferedReader (new InputStreamReader the-stream))] 
    (repeatedly (str (.read reader)))))) 

它給了我下面的錯誤,當我試圖讓first或在任何序列操作結果功能:

java.lang.RuntimeException: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn (repl-1:2) 

此外,使用行seq不工作,因爲(我認爲)該頁面持續太多加載。

我想創建一個懶惰的字符串,因爲簡單地創建一個字符串會給我一個堆空間錯誤。我怎樣才能做到這一點?

+0

更多信息:代碼的最後一行是不起作用的,因爲1)它在'with-open'之外執行'read',這意味着流已經關閉,2)'repeated'接受一個函數,而不是值。 –

回答

2

直接的問題是,反覆期望一個函數,並且給出了(str(....))的結果,這是String。爲了使Clojure的幸福,你需要「包裝」中的「FN」的號召,以「海峽」:

(repeatedly (fn [] (str (.read reader))))) 

一個更好的解決方案是使用啜食或啜食*(後者是在contrib請IIRC),或在至少要檢查它是如何寫入的。

在clojure中沒有「lazy string」這樣的東西。 Clojure字符串只是Java字符串。 Clojure有懶惰的序列,所以你可以嘗試使用它們,但你必須與最後的流進行鬥爭。

或者,也可以使用下面的方法(僞代碼):

(defn process-url [url proc-fn] 
    (with-open [the-stream ...] 
    (loop [c (.read r)] 
     (if-not (neg? c) 
     (proc-fn (char c))))) 

這將調用傳遞作爲第二Arg對每個讀字符的功能。

+0

謝謝你,我正在談論IRC上惰性序列和IO的這個問題,結論是一樣的。我要研究這個問題,看看我能想出什麼解決方案。 –