clojure laziness:防止不必要的mapcat结果实现

时间:2015-01-30 17:39:16

标签: clojure lazy-evaluation

考虑一个查询函数q,它会延迟返回一些(比如十个)结果。

延迟功能:

(defn dlay [x]
  (do
    (Thread/sleep 1500)
    x))

查询功能:

(defn q [pg]
  (lazy-seq
   (let [a [0 1 2 3 4 5 6 7 8 9 ]]
     (println "q")
     (map #(+ (* pg 10) %) (dlay a)))))

通缉行为: 我想产生一个无限的懒惰序列,这样当我获取一个值时,只需要计算所需的计算

错误但有明确的例子:

(drop 29 (take 30 (mapcat q (range))))

如果我没有错,那么它需要评估每个序列,因为它现在还不知道序列的长度。

您将如何获得正确的行为?

我尝试纠正此行为:

(defn getq [coll n]
  (nth 
   (nth coll (quot n 10))
   (mod n 10)))

(defn results-seq []
  (let [a (map q (range))]
    (map (partial getq a)
         (iterate inc 0)))) ; using iterate instead of range, this way i don't have a chunked sequence

但是

(drop 43 (take 44 (results-seq)))

仍然意识到"不需要" q序列。

现在,我确认a是懒惰的,迭代和map应该生成延迟序列,所以问题必须是getq。但是我无法理解它是如何打破我的懒惰的......也许nth在走过一个序列时会意识到事情?如果这是真的,在这种情况下是否有可行的替代方案或我的解决方案遭受糟糕的设计?

0 个答案:

没有答案