2009/4/23 Christophe Grand <christo...@cgrand.net>: > > *Warning this message contains mutable state and may hurt functional > sensibilities.* > > Ugly hack: > > (defn my-split-with [pred coll] > (let [s (atom coll) > p #(when-let [r (pred %)] (swap! s rest) r)] > [(take-while p coll) (drop-while pred (lazy-seq @s))]))
Cheater ! ;-) But there's still the problem of having the user being able to check the second argument before having exhausted (if possible) the first... and then having an infinite loop: e.g. (first (second (my-split-with true? (repeat true))). And maybe calling swap! for each matched elem may be expensive ? (That's a real question, I don't have any real idea, just a guess ...) But wait ... the more I think about it, the more it appears to me (though I can not prove it formally) that the problem requires side-effect to be solved, either via the use of mutation, either via the use of multiple threads for coordinating the feeding of 2 separate sequences ? If I'm correct, then maybe your solution is not that hacky, provided that having to choose between manipulating a state and manipulating multiple threads with BlockingQueues, ... the most efficient, simple and bug free version will certainly be the local mutation of state. With these minor enhancements, your version can also be * very efficient because there will be at most one swap! call (but maybe the overhead I added by adding composition stages is worse than calling swap! each time ?) * much more robust if the user tries to consume from the second seq while not having finished consuming from the first (he will get an exception) Here is the final version, renamed safe-split-with for the occasion: (defn rests [coll] (lazy-seq (if-let [s (seq coll)] (cons s (rests (rest s))) (list ())))) (defn safe-split-with [pred coll] (let [s (atom nil) p #(if-let [r (pred (first %))] true (do (reset! s (second %)) false))] [(map first (take-while p (map vector coll (rests coll)))) (lazy-seq (if-let [s @s] s (throw (IllegalStateException. "Tried to check seq of elems of coll non matching pred before having exhausted seq of elems matching pred."))))])) ; test: (doseq [c (safe-split-with true? [true true false false])] (println c)) ; test exception: (println (second (safe-split-with true? [true true false false]))) --~--~---------~--~----~------------~-------~--~----~ 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 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 -~----------~----~----~----~------~----~------~--~---