```
(->> (repeatedly
       (fn []
         (lazy-seq
           (println "New seq...")
           (map (fn [x] + x (rand-int 10)) (range 4)))))
     (apply concat)
     (take 1))
New seq...
=> (3)
```

Lazy-flatten is unnecessary because concat already does what you want – the
generalised problem you're running in to is that function arguments are
eagerly realised. In your case, your use of concat realises the first two
seqs, in my example, `apply` realises the first four elements (see the
implementation of apply).

If you wrap the seq generator in `lazy-seq` you can delay the realisation
of the 'expensive' inner sequence until concat reaches that list. In
implementation terms, lazy-seq is a macro returns a thunk that will delay
the println (and the sequence generation) until it's required by concat.

On Thu, Nov 23, 2017 at 2:32 AM Matt Anderson <[email protected]>
wrote:

> Thanks! The `aconcat` solution from plumbing works great for this use case.
>
> The `lazy-gen`/`yield` fn's in Tupelo are exactly what I was searching for
> in terms of a larger abstraction, but couldn't quite put into words. Thanks
> for the tip!
>
>
>
> On Wednesday, November 22, 2017 at 2:36:18 AM UTC-5, Alan Thompson wrote:
>
>> You can also solve this using `lazy-gen` and `yield-all` from the Tupelo
>> library
>> <https://github.com/cloojure/tupelo#generator-functions-for-lazy-sequences-a-la-python>.
>> It allows you to make
>> a lazy generator function (a la Python):
>>
>>   (let [seq-of-seqs [(range  0  5)
>>                      (range 10 15)
>>                      (range 20 25)]
>>         flat-seq    (lazy-gen
>>                       (doseq [curr-seq seq-of-seqs]
>>                         (yield-all curr-seq)))]
>>     (is= flat-seq [0 1 2 3 4 10 11 12 13 14 20 21 22 23 24]))
>>
>>
>> Alan
>>
>> On Tue, Nov 21, 2017 at 4:47 PM, Jason Wolfe <[email protected]> wrote:
>>
> I think this
>>> <https://github.com/plumatic/plumbing/blob/318af7798bb701607aaae8639d12829014941184/src/plumbing/core.cljx#L182>
>>> will do it:
>>>
>>> (lazy-cat (first coll) (when-let [n (next coll)] (lazy-flatten n))))
>>>
>>>
>>> On Tuesday, November 21, 2017 at 2:34:15 PM UTC-8, Matt Anderson wrote:
>>>>
>>>> I have a function that is returning a lazy-seq of lazy-seq's.
>>>>
>>>>
>>>> (seq (seq [1 2 3]) (seq [4 5 6]) ...)
>>>>
>>>>
>>>> The end-user API, however, should be able to get back a lazy-seq of the
>>>> individual items across all lazy-seq's--essentially a flattening of the
>>>> output of my function--instead of the "top level" seqs.
>>>>
>>>>
>>>> (seq [1 2 3 4 5 6 ...])
>>>>
>>>> Each of the internal lazy-seq's is expensive in terms of memory usage
>>>> so I'd like to only "load" one at a time.  I've been trying to find a way
>>>> to only calculate one of the top-level lazy-seq's at a time and then not
>>>> "take" the next until the user gets to the end of the first and needs the
>>>> first item from the next (eg: (seq [4 5 6]) doesn't get calculated until we
>>>> have consumed 3 and are asking for the next), but haven't found a way to do
>>>> it. Best I've gotten is "loading" 2 "top level" seqs at a time and I'm
>>>> afraid that may be the best I get, but I thought it might be an exercise
>>>> worth presenting in case anyone had ideas. Here's a contrived example:
>>>>
>>>>
>>>> (defn lazy-flatten
>>>>
>>>>  [coll]
>>>>
>>>>  (when-let [s (seq coll)]
>>>>
>>>>    (lazy-seq
>>>>
>>>>      (if (seq? (first s))
>>>>
>>>>        (concat (lazy-flatten (first s)) (lazy-flatten (rest s)))
>>>>
>>>>        (cons (first s) (lazy-flatten (rest s)))))))
>>>>
>>>> (->> (repeatedly
>>>>        (fn []
>>>>          (println "New seq...")
>>>>          (map (fn [x] + x (rand-int 10)) (range 4))))
>>>>      lazy-flatten
>>>>      (take 1))
>>>>
>>>>
>>>>
>>>> Prints:
>>>>
>>>>
>>>> New seq...
>>>>
>>>> New seq...
>>>>
>>>> => (8)
>>>>
>>>>
>>>> I realize this is because 2 items must be taken for "concat", so there
>>>> would need to be another approach (this was just my best shot
>>>> implementation).
>>>>
>>>>
>>>> Any ideas on how to get the bottom form to only print 1 "New seq..."?
>>>>
>>> --
>>> 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/d/optout.
>>>
>> --
> 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/d/optout.
>
-- 
Stephen Nelson | Platform Lead Developer | Montoux
e.      [email protected] <[email protected]>
t.      @montoux
w.      montoux.com

-- 
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/d/optout.

Reply via email to