lazy-seq question

7 views
Skip to first unread message

Robert Luo

unread,
May 5, 2010, 8:54:31 AM5/5/10
to Clojure
I wrote a function as:

(defn repeated-seq
[f start]
(let [coll (f start)]
(concat coll (lazy-seq (repeated-seq f (last coll))))))

it is OK when I call it with:
(repeated-seq #(range % 5) 0)

the elements are: 0 1 2 3 4 4 5 6 7 8 8 ...

However, I want to get rid of the duplicated index element (4, 8 etc),
e.g.
To produce 0 1 2 3 4 5 6 7 8 9

But when I insert a rest into lazy-seq, the function just hung up.
How can I make this happen?

Thanks.

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Sean Devlin

unread,
May 5, 2010, 9:38:23 AM5/5/10
to Clojure
Where are you inserting the rest? Can you post the new form?

Meikel Brandmeyer

unread,
May 5, 2010, 9:40:17 AM5/5/10
to Clojure
Hi,

On 5 Mai, 14:54, Robert Luo <robort...@gmail.com> wrote:

> (defn repeated-seq
>   [f start]
>   (let [coll (f start)]
>     (concat coll (lazy-seq (repeated-seq f (last coll))))))
>
> it is OK when I call it with:
> (repeated-seq #(range % 5) 0)

repeated-seq cannot do anything about the problem. You have to ensure
that your f is free of "overlap" (so to say). One way todo that in
your example is (repeated-seq #(-> % inc (range 5)) -1).

Also depending on the size of your intermediate seqs you might want to
roll your own concat or use knowledge of the underlying collection
type to avoid the slow last.

(defn roll-your-own-repeated-seq
[f init]
(let [step (fn step
[s]
(lazy-seq
(when-let [[fst & rst] s]
(if rst
(cons fst (step rst))
(cons fst (roll-your-own-repeated-seq f
fst))))))]
(lazy-seq
(step (seq (f init))))))

(defn vector-repeated-seq
[f init]
(lazy-seq
(let [v (f init)]
(when-let [s (seq v)]
(concat s (lazy-seq (vector-repeated-seq f (peek v))))))))

Hope this helps.

Sincerely
Meikel

Krukow

unread,
May 5, 2010, 9:43:51 AM5/5/10
to Clojure


On May 5, 2:54 pm, Robert Luo <robort...@gmail.com> wrote:
[snip]
> (repeated-seq #(range % 5) 0)
>
> the elements are: 0 1 2 3 4 4 5 6 7 8 8 ...

I think you mean,

(def s (repeated-seq #(range % (+ % 5)) 0) )


> However, I want to get rid of the duplicated index element (4, 8 etc),
> e.g.
> To produce 0 1 2 3 4 5 6 7 8 9
>
> But when I insert a rest into lazy-seq, the function just hung up.
> How can I make this happen?

I don't know if this is what you meant, but:

I think it depends on where you put the 'rest'

Try:
(defn repeated-seq
[f start]
(let [coll (f start)]
(concat coll (lazy-seq (rest (repeated-seq f (last coll)))))))

As opposed to

(defn repeated-seq
[f start]
(let [coll (f start)]
(concat coll (rest (lazy-seq (repeated-seq f (last coll)))))))

it isn't particularly efficient, though..

/Karl

Robert Luo

unread,
May 5, 2010, 11:17:51 AM5/5/10
to Clojure
Thanks Meikel.

On 5月5日, 下午9时40分, Meikel Brandmeyer <m...@kotka.de> wrote:
> Hi,
>
> On 5 Mai, 14:54, Robert Luo <robort...@gmail.com> wrote:
>
> > (defn repeated-seq
> > [f start]
> > (let [coll (f start)]
> > (concat coll (lazy-seq (repeated-seq f (last coll))))))
>
> > it is OK when I call it with:
> > (repeated-seq #(range % 5) 0)
>
> repeated-seq cannot do anything about the problem. You have to ensure
> that your f is free of "overlap" (so to say). One way todo that in
> your example is (repeated-seq #(-> % inc (range 5)) -1).

In my example function, f could avoid overlapping by itself. But
sometimes the underlying f is difficult to ensure that, and my
intention is to let repeated-seq to do it rather than leave it to it's
client.

>
> Also depending on the size of your intermediate seqs you might want to
> roll your own concat or use knowledge of the underlying collection
> type to avoid the slow last.
>

Thanks for point out that.

Robert Luo

unread,
May 5, 2010, 11:20:13 AM5/5/10
to Clojure


On 5月5日, 下午9时43分, Krukow <karl.kru...@gmail.com> wrote:
> On May 5, 2:54 pm, Robert Luo <robort...@gmail.com> wrote:
> [snip]
>
> > (repeated-seq #(range % 5) 0)
>
> > the elements are:0 1 2 3 4 4 5 6 7 8 8...
>
> I think you mean,
>
> (def s (repeated-seq #(range % (+ % 5)) 0) )

Nope. The code is what I want to do. The repeated-seq is going to act
as repeatedly.

>
> > However, I want to get rid of the duplicated index element (4, 8 etc),
> > e.g.
> > To produce0 1 2 3 4 5 6 7 8 9
>
> > But when I insert a rest into lazy-seq, the function just hung up.
> > How can I make this happen?
>
> I don't know if this is what you meant, but:
>
> I think it depends on where you put the 'rest'
>
> Try:
> (defn repeated-seq
> [f start]
> (let [coll (f start)]
> (concat coll (lazy-seq (rest (repeated-seq f (last coll)))))))
>
> As opposed to
>
> (defn repeated-seq
> [f start]
> (let [coll (f start)]
> (concat coll (rest (lazy-seq (repeated-seq f (last coll)))))))
>
> it isn't particularly efficient, though..

Both forms can not work. Sorry for not paste them in my original
post.

Meikel Brandmeyer

unread,
May 5, 2010, 3:10:06 PM5/5/10
to clo...@googlegroups.com
Hi,

On Wed, May 05, 2010 at 08:17:51AM -0700, Robert Luo wrote:

> > repeated-seq cannot do anything about the problem. You have to ensure
> > that your f is free of "overlap" (so to say). One way todo that in
> > your example is (repeated-seq #(-> % inc (range 5)) -1).
>
> In my example function, f could avoid overlapping by itself. But
> sometimes the underlying f is difficult to ensure that, and my
> intention is to let repeated-seq to do it rather than leave it to it's
> client.

I think this is the wrong way to go. As it stands repeated-seq might be
a useful function. It cannot know what is overlap and what is not. The
function f must to care of that. Subsequent equal values does not
necessarily mean overlap of some kind. If it is the case for your f,
then you can still filter the resulting seq through distinct or some
uniq style filter.

(defn uniq
[coll]
(lazy-seq
(when-let [s (seq coll)]
(let [f (first s)]
(cons f (uniq (drop-while #(= % f) (rest s))))))))
Reply all
Reply to author
Forward
0 new messages