This answers neither question 1 nor 2, but there is a function from
the map, filter and reduce family of higher order functions that is
applicable to this problem. The function is called unfold and is the
opposite of reduce (see http://en.wikipedia.org/wiki/Anamorphism).

"An unfold builds a (potentially infinite) list from a seed value.
Typically, the unfold takes a seed value x, a one-place operation
unspool that yields a pairs of such items, and a predicate finished
which determines when to finish the list (if ever)."

I could not find unfold or an equivalent function in clojure or
clojure.contrib, so here it is:

(defn unfold [unspool finished x]
  (lazy-seq
    (when-not (finished x)
      (let [[a y] (unspool x)]
        (cons a (unfold unspool finished y))))))

;; the example from the wikipedia page:
(defn iterate-unfold [f x]
  (unfold (fn [a] [a (f a)]) (fn [_] false) x))

=> (take 10 (iterate-unfold inc 0))
(0 1 2 3 4 5 6 7 8 9)

The idea is to pass an unspool function that splits a collection at
every occurrence of an item for which (pred item) is true. The unspool
function in partition-starting-every produces a vector of the
partition "cut off" of the collection and the rest of the collection
to be processed.

(defn partition-starting-every [f coll]
  (unfold (fn [[head & tail]]
            (let [[run more] (split-with (complement f) tail)]
              [(cons head run) more])) empty? coll))

=> (partition-starting-every zero? [1 2 0 1 2 3 0 1 2 3 0 0 1 2])
((1 2) (0 1 2 3) (0 1 2 3) (0) (0 1 2))

The reason that I suggest the unfold function is because it can also
be used for other partitioning functions:

(defn partition-all-unfold [n step coll]
    (unfold (fn [c]
              [(take n c) (drop step c)]) empty? coll))

=> (partition-all 3 2 (range 0 10))
((0 1 2) (2 3 4) (4 5 6) (6 7 8) (8 9))
=> (partition-all-unfold 3 2 (range 0 10))
((0 1 2) (2 3 4) (4 5 6) (6 7 8) (8 9))

Hope this helps,
-Gijs

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to