Веб-поиск в Lazy string ошибка на clojure - PullRequest
3 голосов
/ 26 августа 2011

Я собираюсь получить большую веб-страницу и попробовал это на 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 или любой оператор seq для результата функции:

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

Кроме того, использование line-seq не работает, потому что (я думаю) страница слишком долго загружается.

Я хотел создать ленивую строку, потому что создание простой строки приводит к ошибке из-под кучи. Как мне это сделать?

1 Ответ

2 голосов
/ 26 августа 2011

Непосредственная проблема состоит в том, что многократно ожидает функцию, и вы даете результат (str (....)), который является String. Чтобы сделать Clojure счастливым, вам нужно «упаковать» вызов «str» в «fn»:

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

Лучшее решение - использовать slurp или slurp * (последний есть в contrib IIRC) или, по крайней мере, проверить, как оно написано.

[править] Там нет такой вещи, как "ленивая строка" в clojure. Строки 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)))))

Это вызовет функцию, которую вы передаете в качестве второго аргумента для каждого прочитанного символа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...