-->

在Clojure中,是懒惰seqs总是分块?(In Clojure, are lazy seqs a

2019-06-28 09:05发布

我是懒惰seqs总是分块的印象。

=> (take 1 (map #(do (print \.) %) (range)))
(................................0)

如所预期的32点被打印,因为返回的懒惰SEQ range被分块成32个元件块。 然而,不是在range我尝试这与我自己的函数get-rss-feeds ,懒惰序列不再分块:

=> (take 1 (map #(do (print \.) %) (get-rss-feeds r)))
(."http://wholehealthsource.blogspot.com/feeds/posts/default")

只有一个点被打印出来,所以我想通过返回的懒惰-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依赖于懒惰序列是如何产生的。 我偷看在源的功能range并有一个“粗碎块”方式来实现它的提示。 所以我有点困惑,这是如何工作。 有人请澄清?


这也是为什么我需要知道的。

我有下面的代码: (get-rss-entry (get-rss-feeds h-res) url)

因此,要求get-rss-feeds返回我需要检查饲料的URL的懒惰序列。

因此,要求get-rss-entry查找特定条目(其:链接字段GET-RSS条目的第二个参数匹配)。 它检查返回的懒惰序列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 ,如果没有匹配返回匹配的懒惰序列或空序列。

我测试了这一点,它似乎正常工作(评估一次一个供稿网址)。 但我担心的地方,不知它会启动一个“矮胖”的行为方式,它会开始以时间来评估32吨饲料。 我知道有一种方法,以避免因为这里讨论矮胖的行为 ,但它似乎没有,即使在这种情况下是必需的。

我使用的懒惰SEQ非惯用? 将循环/易复发是更好的选择?

Answer 1:

根据分块的模糊性,你上面提到似乎是不明智的。 明确将“未分块”在你真的需要它不被分块的情况下也是明智的,因为这时如果在其他一些点在chunkifies它的东西不会打破这样你的代码更改。 在另一方面, 如果你需要的动作是连续的,代理是一个很好的工具 ,你可以发送下载功能,代理那么他们将被运行一次一个只有一次,无论你如何评价的功能。 在某些时候,你可能要pmap您的序列,然后甚至未分块虽然不会使用原子将继续正常工作运行。



Answer 2:

你是正确的关注。 您get-rss-entry的确会调用entry-with-url不是绝对必要的更多,如果feeds参数是返回分块seqs的集合。 例如,如果feeds是矢量, map将在整个组块在一个时间进行操作。

此问题是Clojure Fogus' 直接寻址,用函数seq1在第12章中定义:

(defn seq1 [s]
  (lazy-seq
    (when-let [[x] (seq s)]
      (cons x (seq1 (rest s)))))) 

你可以用这个吧,你知道你最想要的懒惰可能的,你叫右前entry-with-url

(defn get-rss-entry
  [feeds url]
  (ffirst (drop-while empty? (map #(entry-with-url % url) (seq1 feeds)))))


Answer 3:

懒seqs 并不总是分块 -这取决于它们是如何产生的。

例如,由该函数产生的懒惰SEQ没有分块:

(defn integers-from [n]
  (lazy-seq (cons n (do (print \.) (integers-from (inc n))))))

(take 3 (integers-from 3))
=> (..3 .4 5)

但许多其他的Clojure内置函数确实产生性能方面的原因分块seqs(如范围 )



文章来源: In Clojure, are lazy seqs always chunked?