Seems these guys below have the same problem, and everyone thinks it is 
`apply` or `concat` to blame. One of the answerer even explains how apply 
is the issue, but in the reimplemented version of `mapcat` beside throwing 
out `apply` he does not use `map` either:

http://stackoverflow.com/questions/4290665/does-concat-break-the-laziness-of-line-seq
http://stackoverflow.com/questions/16194841/clojure-lazy-sequences-in-math-combinatorics-results-in-outofmemory-oom-error/16270113#16270113

On Sunday, July 14, 2013 2:33:56 AM UTC+1, Daniel Dinnyes wrote:
>
> Hiya, check this code out guys:
> ----
>
> (defn point [x y]
>   (println "x:" x "y:" y)
>   [x y])
>
> (defn gen-data [n m]
>   (for [i (range n)]
>     (for [j (range m)]
>       (point i j))))
>
> (def data (apply concat (gen-data 100 100)))
>
> (nth data 5)
>
> "The output was the following:"
>
> "x: 0 y: 0
>  x: 0 y: 1
>  x: 0 y: 2
>  x: 0 y: 3
>  x: 0 y: 4
>  x: 0 y: 5
>  x: 0 y: 6
>  x: 0 y: 7
>  x: 0 y: 8
>  x: 0 y: 9
>  x: 0 y: 10
>  x: 0 y: 11
>  x: 0 y: 12
>  x: 0 y: 13
>  x: 0 y: 14
>  x: 0 y: 15
>  x: 0 y: 16
>  x: 0 y: 17
>  x: 0 y: 18
>  x: 0 y: 19
>  x: 0 y: 20
>  x: 0 y: 21
>  x: 0 y: 22
>  x: 0 y: 23
>  x: 0 y: 24
>  x: 0 y: 25
>  x: 0 y: 26
>  x: 0 y: 27
>  x: 0 y: 28
>  x: 0 y: 29
>  x: 0 y: 30
>  x: 0 y: 31
>  [0 5]"
>
> "Seems like other people have similar problems but the issue was 
> mis-attributed,
> as they thought it has to do with `apply` and/or `concat` (read further to 
> find out why not):
> https://groups.google.com/forum/#!topic/clojure/vzhFmpGkWTo
> http://clojurian.blogspot.co.uk/2012/11/beware-of-mapcat.html";
>
> "First I too was suspicious about `concat` and `apply`, so I wrote a 
> version of concat which was not using varargs."
>
> (defn concat2 [coll]
>   (lazy-seq
>    (if-let [s (seq coll)]
>      (if-let [ss (seq (first s))]
>        (cons (first ss) (concat2 (cons (rest ss) (rest s))))
>        (concat2 (rest s)))
>      nil)))
>
> (def data (apply concat (gen-data 100 100)))
>
> (nth data 5)
>
> "The issue was still there unfortunately, exactly the same printout like 
> the with the first example"
>
> "So next i became suspicious of `for`. Maybe it has to do with the way it 
> is evaluated. So I rewrote `gen-data` using `map`"
>
> (defn gen-data [n m]
>   (map (fn [x]
>          (map (fn [y] (point x y))
>               (range m)))
>        (range n)))
>
> "Even with `map` the issue was still present. Maybe both `map` and `for` 
> has the same problem? Let's rewrite `map` then"
>
> (defn map2 [f coll]
>   (lazy-seq
>    (if-let [s (seq coll)]
>      (cons (f (first s))
>            (map2 f (rest s)))
>      nil)))
>
> (defn gen-data [n m]
>   (map2 (fn [x]
>          (map2 (fn [y] (point x y))
>               (range m)))
>        (range n)))
>
> (def data (apply concat (gen-data 100 100)))
>
> (nth data 5)
>
> "x: 0 y: 0
>  x: 0 y: 1
>  x: 0 y: 2
>  x: 0 y: 3
>  x: 0 y: 4
>  x: 0 y: 5
>  [0 5]"
>
> "GOTCHA!!! WORKS CORRECTLY!!! BUG FOUND!!!"
>
> "...seems like both `map` and `for` are affected, possibly because `for` 
> depends on `map` (just assumption sorry, I was L.A.Z.Y. to check)"
>
> "Also, the bug was present while testing with both Clojure versions 1.4 
> and 1.5.1"
>
> "Finally, just to emphasize how serious the issue is try the same with 
> ONLY three levels of nested \"mapcatting\":"
>
> (defn point3d [x y z]
>     (println "x:" x "y:" y "z:" z)
>     [x y z])
>
> (defn gen-data3d [n m k]
>   (mapcat (fn [x]
>          (mapcat (fn [y]
>                    (mapcat (fn [z] [(point3d x y z)])
>                            (range k)))
>                  (range m)))
>        (range n)))
>
> (def data3d (gen-data3d 100 100 100))
>
> (nth data3d 5)
>
> "Not gonna copy the output here... seems like if the number of nested 
> level of mapcats is `n` then the total number of elements evaluating 
> non-lazily in one go is 32^n."
>
> ---
> BTW, the `map2` implementation above is the quite matching 
> clojure.core/map, except the core version has special handling for 
> ChunkedSeqs. Most probably the issue comes from there. Can someone look 
> into this please?
>
> Thanks,
> Daniel
>
>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to