从懒惰的seq中获取所有实现的值

时间:2014-08-27 14:49:18

标签: clojure

;; create lazy infinite seq of random ints
(def infi-seq (repeatedly #(rand-int 11)))
(take 5 infi-seq) ; => (8 2 9 9 5)

如果不知道前五个值已经实现,我怎样才能实现所有值(8 2 9 9 2)

3 个答案:

答案 0 :(得分:4)

这应该可以解决问题:

(defn take-realized
  [coll]
  (if-not (instance? clojure.lang.IPending coll)
    (cons (first coll) (take-realized (rest coll)))
    (when (realized? coll)
       (cons (first coll) (take-realized (rest coll))))))

答案 1 :(得分:2)

您可以修改或使用count-realized

(defn count-realized [s] 
  (loop [s s, n 0] 
    (if (instance? clojure.lang.IPending s)
      (if (and (realized? s) (seq s))
        (recur (rest s) (inc n))
        n)
      (if (seq s)
        (recur (rest s) (inc n))
        n))))

注意,对于非延迟元素前置序列的情况,检查IPend是必要的,如迭代。


(def foo (iterate inc 1))

(take (count-realized foo) foo)
;=> (1)

(dorun (take 5 foo))
;=> nil

(take (count-realized foo) foo)
;=> (1 2 3 4 5)

答案 2 :(得分:1)

也许这就是:

(defn take-realized [coll]
  (map first (take-while realized? (iterate rest coll))))

整洁而又简单。它可以在某种程度上修复:

(defn take-realized [coll]
  (->> coll
       (iterate next)
       (take-while #(and % (or (not (instance? clojure.lang.IPending %)) (realized? %))))
       (map first)))

但这仍然会产生iterate的无限延迟序列:

(take 5 (take-realized (iterate inc 0)))
;(0 1 2 3 4) 

其他答案都很优秀。