I am not sure we need finished arg though. The traditional finish in
the seq family is nil.
My own version of unfold:
(defn unfold
"(unfold seed grow) use the seed and a function grow that returns an
element and another seed
to creates a lazy seq.
The seq is stopped the grow function returns nil."
[seed grow]
(if-let [[elt next-seed] (grow seed)]
(cons elt
(lazy-seq (unfold next-seed grow)))
()))
Whether the cons is in or outside the lazy-seq is debatable. (I like
to think of seq as the fixpoint of the functor (X -> Cons Object (lazy
X)))
Best,
Nicolas.
Iteration at a rate other than once per input seq item suggests iterate:
(defn partition-starting-every [f coll]
(->> [nil coll]
(iterate (fn [[p [x :as s1]]]
(let [[n s2] (split-with (complement f) (next s1))]
(when (seq s1)
[(cons x n) s2]))))
(map first)
next
(take-while identity)))
Ugh. Well, maybe partition-by can be used after all:
(defn partition-starting-every [f coll]
(let [pb (partition-by #(and (f %) (Object.)) coll)]
(->> (map (fn [[a :as as] [b :as bs]]
(cond
(nil? as) (when-not (f b) bs)
(and (f a) (f b)) as
(f a) (concat as bs)))
(cons nil pb) pb)
(remove nil?))))
Bleh. Looks lazy-seq is the way to go. :-)
BTW, it's generally best to have the lazy-seq outside the empty
test to make your fn as lazy as possible. And I'd use split-with:
(defn partition-starting-every
"Partition the sequence starting each partition when the f is true."
[f coll]
(lazy-seq
(when-let [[x & xs] (seq coll)]
(let [[a b] (split-with (complement f) xs)]
(cons (cons x a) (partition-starting-every f b))))))
--Chouser
http://joyofclojure.com/
On Fri, Sep 10, 2010 at 4:26 PM, Matt Smith <m0s...@gmail.com> wrote:
> problem: convert a collection [1 2 0 1 2 3 0 1 2 3 0 0 1 2] into
> partitions like:
> ((1 2) (0 1 2 3) (0 1 2 3) (0) (0 1 2))
> In this case, start each partition on a 0.
Iteration at a rate other than once per input seq item suggests iterate:
(->> [nil coll]
(defn partition-starting-every [f coll]
(iterate (fn [[p [x :as s1]]]
(let [[n s2] (split-with (complement f) (next s1))]
(when (seq s1)
[(cons x n) s2]))))
(map first)
next
(take-while identity)))
Ugh. Well, maybe partition-by can be used after all:
(let [pb (partition-by #(and (f %) (Object.)) coll)]
(defn partition-starting-every [f coll]
(->> (map (fn [[a :as as] [b :as bs]]
(cond
(nil? as) (when-not (f b) bs)
(and (f a) (f b)) as
(f a) (concat as bs)))
(cons nil pb) pb)
(remove nil?))))
(unfold (fn [x] (when (<= x 10) [(* x x) (inc x)])) would work.
Both function can be written with each other anyway.
And they don't have the same number of args so they are compatible
with each other.
> --
> 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
--
Sent from an IBM Model M, 15 August 1989.
(unfold (fn [x] [(* x x) (inc x)]) #(> % 10) 0)
(0 1 4 9 16 25 36 49 64 81 100)
(unfold (fn [x] (when (<= x 10) [(* x x) (inc x)])) 0)
(0 1 4 9 16 25 36 49 64 81 100)
I think it can be proved that any sequence can be build with a call to unfold.
Which makes it useful and solves the
"why reduce is not lazy?" question.
The implement is equivalent, most languages I know that has unfold use
your approach(i.e. return Maybe<e,s> or None).
This link use the unfold p f g form