Reputation: 8113
I have an infinite lazy sequence that produce a "preamble" and a "pattern repetition", a simple example of this kind of sequence could be implemented in Clojure with:
(def infinite-lazy-sequence
(lazy-cat [4] (cycle [1 2 3])))
=> (take 20 infinite-lazy-sequence)
(4 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1)
I would like to get a set
of the elements forming this infinite-lazy-sequence
, here is a way to implement it using loop
:
(loop
[[head & tail] infinite-lazy-sequence
result #{}]
(if (contains? result head)
result
(recur tail (conj result head))))
=> #{1 2 3 4}
Here is the question: is it possible to achieve the same result using reduce
? And using take-while
?
Edit:
Benchmark results using clojure-1.5.1 and perforate-0.2.4
proposed loop-recur
implementation:
Case: :loop-recur
Evaluation count : 60 in 60 samples of 1 calls.
Execution time mean : 1.054975 sec
Execution time std-deviation : 26.316442 ms
Execution time lower quantile : 1.026187 sec ( 2.5%)
Execution time upper quantile : 1.125854 sec (97.5%)
@sw1nn reduce-reduced
implementation:
Case: :reduce-reduced
Evaluation count : 120 in 60 samples of 2 calls.
Execution time mean : 875.091831 ms
Execution time std-deviation : 19.745142 ms
Execution time lower quantile : 850.871606 ms ( 2.5%)
Execution time upper quantile : 921.947759 ms (97.5%)
Upvotes: 2
Views: 1387
Reputation: 7328
Clojure 1.5 added reduced
to allow shortcircuiting reduces...
(reduce (fn [a v] (if-not (a v) (conj a v) (reduced a)))
#{}
infinite-lazy-sequence)
=> #{1 2 3 4}
Upvotes: 4