Get all implemented values ​​from lazy seq

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

How can I get all implemented values (8 2 9 9 2)without knowing that the first five values ​​are implemented?

+4
source share
3 answers

This should do the trick:

(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))))))
+4
source

You can change or use an invoice-implemented

(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))))

Note that checking for IPending is necessary for cases where non-lazy elements add a sequence, as in an iteration.


(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
source

, :

(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) 

.

+1

All Articles