开发者

Web retrieval to Lazy string error on clojure

开发者 https://www.devze.com 2023-03-31 12:44 出处:网络
I intend to retrieve a big web page and tried this on Clojure (defn fetch-url [url] \"Retrieves the web page specified by the url.\"

I intend to retrieve a big web page and tried this on 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))))))

It gives me the following error when I try to get the first or any seq operator on the result of the function:

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

Also, using line-seq doesn't work because (I think) the page lasts开发者_JS百科 too much loading.

I wanted to create a lazy string because creating simply a string gives me an out of heap space error. How can I accomplish this?


The immediate problem is, that repeatedly expects a function, and you're giving the result of (str (....)), which is String. To make Clojure happy, you need to "pack" the call to "str" in "fn":

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

A better solution is to use slurp or slurp* (the latter is in contrib IIRC), or at least to check out how it is written.

[edit] There's no such thing as "lazy string" in clojure. Clojure strings are just java strings. Clojure has lazy sequences so you can try using them, but you'll have to fight with the closing stream.

Alternatively, you can use the following approach (pseudo-code):

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

This will call the function you pass as a second arg on each read character.

0

精彩评论

暂无评论...
验证码 换一张
取 消