Reputation: 388
I am hoping to generate all the multiples of two less than 10 using the following code
(filter #(< % 10) (iterate (partial + 2) 2))
Expected output:
(2 4 6 8)
However, for some reason repl just doesn't give any output?
But, the below code works just fine...
(filter #(< % 10) '(2 4 6 8 10 12 14 16))
I understand one is lazy sequence and one is a regular sequence. That's the reason. But how can I overcome this issue if I wish to filter all the number less than 10 from a lazy sequence...?
Upvotes: 7
Views: 1552
Reputation: 13079
(iterate (partial + 2) 2)
is an infinite sequence. filter
has no way to know that the number of items for which the predicate is true is finite, so it will keep going forever when you're realizing the sequence (see Mark's answer).
What you want is:
(take-while #(< % 10) (iterate (partial + 2) 2))
Upvotes: 10
Reputation: 7599
I think I should note that Diego Basch's answer is not fully correct in its argumentation:
filter
has no way to know that the number of items for which the predicate is true is finite, so it will keep going forever
Why should filter
know something about that? Actually filter
works fine in this case. One can apply filter
on a lazy sequence and get another lazy sequence that represent potentially infinite sequence of filtered numbers:
user> (def my-seq (iterate (partial + 2) 2)) ; REPL won't be able to print this
;; => #'user/my-seq
user> (def filtered (filter #(< % 10) my-seq)) ; filter it without problems
;; => #'user/filtered
user>
Crucial detail here is that one should never try to realize (by printing in OP's case) lazy sequence when actual sequence is not finite for sure (so that Clojure knows that).
Of course, this example is only for demonstration purposes, you should use take-while
here, not filter
.
Upvotes: 6