0

I have this function which seems to work fine on limited collections, but not on infinite ones. Is there a way to construct a lazy-seq in it to get it run with infinite coll's, like: (take 3 (m inc (range))) => (1 2 3)?

(defn m [f c] (reduce #(conj % (f %2)) [] c))

2 Answers 2

2

This seems to be a use case for map

(map f c)

or (when it had to be a vector)

(mapv f c)

EDIT: A possible re-implementation of map:

(defn new-map [f coll]
  (if (seq coll)
    (lazy-seq
      (cons (f (first coll)) 
            (new-map f (rest coll))))))
Sign up to request clarification or add additional context in comments.

5 Comments

I was trying to make something like map
So you want to re-implement map?
is it possible to use the lazy-seq on other expression bodies, like in my example? something like : (defn m [f c] (lazy-seq (reduce #(conj % (f %2)) [] c)))
You can't use reduce to be lazy. When you "put" something thing in a lazy seq, then thing will not get lazy! It will remain the same. The laziness you get by using lazy-seq is the following: the thing in the seq will only be evaluate when you reach/look at thing in the seq. The result of your function m is exactly the same as (mapv f c)
no, reduce is not lazy, it has to realize whole reduced collection. And wrapping it to lazy-seq won't help at all
1

reduce will keep taking elements from a sequence until nil gets returned. As such, reduce will never return on infinite sequences.

As pointed out in the comments, reduced can be used to force the termination of reduce, thanks!

3 Comments

Well, you can use reduced to terminate on infinite seqs.
This means put reduce inside an if expression?
Yes, you can check the examples over here: clojuredocs.org/clojure.core/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.