> I summarised my issues with the different solutions. Since things got > a bit philosophical I wrote up a short blog post on my point of view: > http://bit.ly/hInw0J
I'm surprised to hear that partition-by is not very lazy, and will hang on an infinite seq. Fortunately, that can be fixed: (defn partition-by [f s] (lazy-seq (let [s (seq s)] (if s (let [fs (map f s) eq (cons true (map = fs (rest fs))) eqs (seq (map list eq s)) step (fn step [eqs] (lazy-seq (let [eqs (seq eqs)] (if eqs (cons (lazy-seq (cons (second (first eqs)) (map second (take-while first (rest eqs))))) (step (drop-while first (rest eqs))))))))] (step eqs)))))) A bit long and convoluted, with no fewer than three applications of lazy-seq, but fully lazy: user=> (defn report-seq [] (letfn [(this [i] (lazy-seq (prn (str ">" i "<")) (cons i (this (inc i)))))] (take 14 (this 0)))) #'user/report-seq user=> (def q (partition-by #(quot % 3) (report-seq))) #'user/q ; No elements realized user=> (def q (first (partition-by #(quot % 3) (report-seq)))) ">0<" #'user/q ; Had to realize 0 to know whether to return nil or a lazy-seq object here user=> (def q (first (first (partition-by #(quot % 3) (report-seq))))) ">0<" #'user/q ; Realized only the element it returned user=> (def q (second (partition-by #(quot % 3) (report-seq)))) ">0<" ">1<" ">2<" ">3<" ; Realized up to the first element of the next chunk, to know if that ; chunk existed user=> (partition-by #(quot % 3) (report-seq)) ">0<" ((0">1<" 1">2<" 2">3<" ) (3">4<" 4">5<" 5">6<" ) (6">7<" 7">8<" 8">9<" ) (9">10<" 10">11<" 11">12<" ) (12">13<" 13)) ; Each element realized only as it's needed during a full traversal user=> (take 5 (partition-by #(quot % 3) (iterate inc 0))) ((0 1 2) (3 4 5) (6 7 8) (9 10 11) (12 13 14)) ; Does not blow up on infinite input seq user=> (defn report-fn [x] (println "Expensive computation would have been run on: " x) (quot x 3)) #'user/report-fn user=> (def q (doall (map doall (partition-by report-fn (range 14))))) Expensive computation would have been run on: 0 Expensive computation would have been run on: 1 Expensive computation would have been run on: 2 Expensive computation would have been run on: 3 Expensive computation would have been run on: 4 Expensive computation would have been run on: 5 Expensive computation would have been run on: 6 Expensive computation would have been run on: 7 Expensive computation would have been run on: 8 Expensive computation would have been run on: 9 Expensive computation would have been run on: 10 Expensive computation would have been run on: 11 Expensive computation would have been run on: 12 Expensive computation would have been run on: 13 #'user/q ; The potentially-expensive f is only run once per item during a full traversal -- 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