On Nov 8, 12:33 pm, Michael Jaaka <michael.ja...@googlemail.com>
wrote:
>
> now I would like get such effect that callbackListener will be called twice
> for the example collection.
>
> once with "tom" and iterator (or a lazy seq) to lazy evaluated collection of
> (32 and 2333)
> and second with "anne" and iterator for collection of (12 and 55)
<snip>
> Note that all must be evaluated lazily.

Unless the keys in your sequence will always be sorted, I don't
believe you can do this lazily; in order to generate a sequence of the
values for a given key in your collection, you would have to traverse
the entire collection first in order to check each key, i.e. if you
had:

[[ "tom" 32 ] [ "anne" 12 ] [ "anne" 55 ] [ "tom" 2333 ]]

Then you'd need to get right to the end of the list in order to
generate the sequence of values for "tom".

One, non-lazy, way to accomplish what you're after would be:

(use '[clojure.contrib.seq-utils :only (group-by)])

(def *s* [["tom" 32] ["tom" 2333] ["anne" 12] ["anne" 55]])

(defn callback-listener
  [k v]
  (println (str "key: " k ", value: " v)))

(doseq [[k v] (map (fn [[k v]] [k (map second v)])
                   (group-by first *s*))]
  (callback-listener k v))

Note that since you used the name "callback-listener", I'm assuming
that it has side effects, which is why I used doseq.  If callback-
listener does _not_ have side effects (i.e. if it performs some
computation upon it's arguments and simply yields a result, then you
could use:

(defn callback-fn
  [[k v]]
  (compute-some-value-from-arguments k v))

(map (comp callback-fn (fn [[k v]] [k (map second v)]))
     (group-by first *s*))

which would yield a sequence of the result of each call to callback-
fn2.  Note that while the resulting sequence would, technically, be
lazy, group-by is not, so you would still consume the entire input
sequence up front.

Now, _if_ you can guarantee that your input sequence will always be
sorted by key (that is, if you know for a fact that all the entries
for a given key will be consecutive, as in your example: [tom tom anne
anne], rather than mine above: [tom anne tom anne]), then you could
use partition-by instead, which would (I believe) let you achieve full
laziness:

(use '[clojure.contrib.seq-utils :only (partition-by)])

(map (comp callback-fn (fn [part] [(ffirst part) (map second part)]))
     (partition-by first *s*))

Hope this helps,

-David

--~--~---------~--~----~------------~-------~--~----~
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