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 Answers2

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))))))
user5187212
  • 426
  • 2
  • 7
  • I was trying to make something like `map` –  Oct 08 '15 at 19:20
  • So you want to re-implement map? – user5187212 Oct 08 '15 at 19:23
  • 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))) ` –  Oct 08 '15 at 20:11
  • 1
    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)` – user5187212 Oct 08 '15 at 21:27
  • 1
    no, reduce is not lazy, it has to realize whole reduced collection. And wrapping it to lazy-seq won't help at all – leetwinski Oct 08 '15 at 21:29
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!

Nils Blum-Oeste
  • 5,608
  • 4
  • 25
  • 26