レイジー seq は常にチャンクされているという印象を受けました。
=> (take 1 (map #(do (print \.) %) (range)))
(................................0)
によって返されるレイジー seq はrange
32 要素のチャンクに分割されるため、予想どおり 32 ドットが出力されます。ただし、代わりにrange
自分の関数でこれを試すとget-rss-feeds
、遅延シーケンスはチャンクされなくなります。
=> (take 1 (map #(do (print \.) %) (get-rss-feeds r)))
(."http://wholehealthsource.blogspot.com/feeds/posts/default")
ドットが 1 つだけ出力されるので、返される 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])))
そのため、チャンク性は、レイジー seq の生成方法に依存するようです。関数のソースをのぞき見したところrange
、「分厚い」方法で実装されているというヒントがあります。だから私はこれがどのように機能するかについて少し混乱しています。誰かが明確にしてもらえますか?
これが私が知る必要がある理由です。
次のコードが必要です。(get-rss-entry (get-rss-feeds h-res) url)
を呼び出すとget-rss-feeds
、調べる必要のあるフィードの URL の遅延シーケンスが返されます。
への呼び出しget-rss-entry
は、特定のエントリ (:link フィールドが get-rss-entry の 2 番目の引数と一致する) を探します。によって返された遅延シーケンスを調べますget-rss-feeds
。各項目を評価するには、新しい RSS フィードを取得するためにネットワーク経由で http 要求が必要です。http リクエストの数を最小限に抑えるには、シーケンスを 1 つずつ調べて、一致したらすぐに停止することが重要です。
コードは次のとおりです。
(defn get-rss-entry
[feeds url]
(ffirst (drop-while empty? (map #(entry-with-url % url) feeds))))
entry-with-url
一致の遅延シーケンスを返すか、一致がない場合は空のシーケンスを返します。
これをテストしたところ、正しく動作しているようです (一度に 1 つのフィード URL を評価します)。しかし、どこかで、どういうわけか「分厚い」方法で動作し始め、一度に 32 個のフィードを評価し始めるのではないかと心配しています。here で説明されているように、チャンキーな動作を回避する方法があることは知っていますが、この場合は必要ではないようです。
非慣用的にレイジー seq を使用していますか? ループ/再帰はより良い選択肢でしょうか?