У меня создалось впечатление, что ленивые секции всегда были помечены.
=> (take 1 (map #(do (print \.) %) (range)))
(................................0)
Как и ожидалось, напечатано 32 точки, потому что ленивый seq, возвращаемый range
, разбивается на 32 элементарных фрагмента. Однако, когда вместо range
я пытаюсь выполнить эту функцию со своей собственной функцией get-rss-feeds
, lazy seq больше не кланяется:
=> (take 1 (map #(do (print \.) %) (get-rss-feeds r)))
(."http://wholehealthsource.blogspot.com/feeds/posts/default")
Печатается только одна точка, поэтому я думаю, что lazy-seq, возвращаемый get-rss-feeds
, не разбивается на разделы. Действительно:
=> (chunked-seq? (seq (range)))
true
=> (chunked-seq? (seq (get-rss-feeds r)))
false
Вот источник для get-rss-feeds
:
(defn get-rss-feeds
"returns a lazy seq of urls of all feeds; takes an html-resource from the enlive library"
[hr]
(map #(:href (:attrs %))
(filter #(rss-feed? (:type (:attrs %))) (html/select hr [:link])))
Таким образом, кажется, что chunkiness зависит от того, как создается ленивый seq. Я заглянул в источник для функции range
, и есть намеки на то, что она выполняется "коротко". Поэтому я немного смущен относительно того, как это работает. Может кто-то прояснить?
Вот почему мне нужно знать.
Мне нужен следующий код: (get-rss-entry (get-rss-feeds h-res) url)
Вызов get-rss-feeds
возвращает ленивую последовательность URL-адресов фидов, которые мне нужно изучить.
Вызов get-rss-entry
ищет определенную запись (чье: поле ссылки соответствует второму аргументу get-rss-entry). Он проверяет ленивую последовательность, возвращаемую get-rss-feeds
. Для оценки каждого элемента требуется HTTP-запрос по сети для получения нового rss-канала. Чтобы свести к минимуму количество HTTP-запросов, важно проанализировать последовательность один за другим и остановить, как только будет соответствие.
Вот код:
(defn get-rss-entry
[feeds url]
(ffirst (drop-while empty? (map #(entry-with-url % url) feeds))))
entry-with-url
возвращает ленивую последовательность совпадений или пустую последовательность, если нет совпадения.
Я тестировал это и, похоже, работал правильно (оценивая один URL канала одновременно). Но я обеспокоен тем, что где-то он начнет вести себя "коротким" способом, и он начнет оценивать 32 канала за раз. Я знаю, что существует способ избегать короткого поведения, как обсуждалось здесь, но в этом случае это не кажется даже обязательным.
Я использую ленивый seq не-идиоматически? Будет ли цикл/повторение лучшим вариантом?