Re: Analog to Scheme's partition in Clojure?
Ben Wolfson writes: Hi Ben, >> However, the what's bad with the juxt approach above is that the >> collection is iterated twice. If somebody comes up with a version >> that returns a vector of two lazy seqs and which iterates the input >> collection only once, she'd get my warmest thank you, and my vote for >> putting it into core. > > here's a first shot, kind of ugly but seems to work: > > user> (defn seqmr > [f g a bs] > (lazy-seq >(if (seq bs) > (g (f (first bs)) (seqmr f g a (rest bs))) > a))) > #'user/seqmr > user> (defn lazy-partition [p xs] > (seqmr (fn [x] >[(p x) x]) > (fn [[t? x] r] >(if t? > [(lazy-seq (cons x (first r))) (lazy-seq (second r))] > [(lazy-seq (first r)) (lazy-seq (cons x (second r)))])) > [() ()] > xs)) > #'user/lazy-partition Hey, cool, my warmest thank you! :-) But although it iterates the seq just ones and thus applies the predicate just once to every element, it's way slower than the juxt approach. user> (time (let [[e o] (lazy-partition even? (range 100))] (dorun e) (dorun o))) "Elapsed time: 4806.654139 msecs" nil user> (time (let [[e o] ((juxt filter remove) even? (range 100))] (dorun e) (dorun o))) "Elapsed time: 424.327826 msecs" nil Well, if the predicate becomes expensive, it'll start becoming faster, though. user> (time (let [[e o] (lazy-partition (fn [x] (Thread/sleep 5) (even? x)) (range 100))] (dorun e) (dorun o))) "Elapsed time: 513.543943 msecs" nil user> (time (let [[e o] ((juxt filter remove) (fn [x] (Thread/sleep 5) (even? x)) (range 100))] (dorun e) (dorun o))) "Elapsed time: 1025.856917 msecs" nil Bye, Tassilo -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Analog to Scheme's partition in Clojure?
On Thu, Apr 4, 2013 at 8:44 AM, Tassilo Horn wrote: > > However, the what's bad with the juxt approach above is that the > collection is iterated twice. If somebody comes up with a version that > returns a vector of two lazy seqs and which iterates the input > collection only once, she'd get my warmest thank you, and my vote for > putting it into core. > > here's a first shot, kind of ugly but seems to work: user> (defn seqmr [f g a bs] (lazy-seq (if (seq bs) (g (f (first bs)) (seqmr f g a (rest bs))) a))) #'user/seqmr user> (defn lazy-partition [p xs] (seqmr (fn [x] [(p x) x]) (fn [[t? x] r] (if t? [(lazy-seq (cons x (first r))) (lazy-seq (second r))] [(lazy-seq (first r)) (lazy-seq (cons x (second r)))])) [() ()] xs)) #'user/lazy-partition user> (def r (lazy-partition even? (map #(do (print % "") %) (range 129 #'user/r user> (first (first r)) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0 user> (first (second r)) 1 user> (nth (second r) 10) 21 user> (nth (second r) 20) 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 41 user> (nth (first r) 20) 40 -- Ben Wolfson "Human kind has used its intelligence to vary the flavour of drinks, which may be sweet, aromatic, fermented or spirit-based. ... Family and social life also offer numerous other occasions to consume drinks for pleasure." [Larousse, "Drink" entry] -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Analog to Scheme's partition in Clojure?
Yes it is indeed cool but it suffers from the same problem as the juxt version (as Tassillo mentioned)...they are both very elegant and succinct but unfortunately slow for large sequences. The group-by version and the doseq version are way faster...also, there is a reducer-based filter if you want go parallel... you asked where to find this funciton... a couple of places actually :) http://clojuredocs.org/clojure_contrib/clojure.contrib.seq-utils/separate http://richhickey.github.com/clojure-contrib/seq-utils-api.html HTH, Jim On 04/04/13 19:12, Christian Romney wrote: On Thursday, April 4, 2013 12:13:13 PM UTC-4, Jim foo.bar wrote: there is a separate fn in contrib and does exactly what you want (assuming you don't care about the 2 passes): (defn separate "Returns a vector: [ (filter f s), (filter (complement f) s) ]" [f s] [(filter f s) (filter (complement f) s)]) Very cool—where can I find this? I ask because there may be other goodies I should be aware of... I also like Tassilo's version using juxt. It's great to see the same problem solved different ways. -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Analog to Scheme's partition in Clojure?
On Thursday, April 4, 2013 12:13:13 PM UTC-4, Jim foo.bar wrote: > there is a separate fn in contrib and does exactly what you want > (assuming you don't care about the 2 passes): > > (defn separate > "Returns a vector: >[ (filter f s), (filter (complement f) s) ]" > [f s] > [(filter f s) (filter (complement f) s)]) > > Very cool—where can I find this? I ask because there may be other goodies I should be aware of... I also like Tassilo's version using juxt. It's great to see the same problem solved different ways. -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Analog to Scheme's partition in Clojure?
there is a separate fn in contrib and does exactly what you want (assuming you don't care about the 2 passes): (defn separate "Returns a vector: [ (filter f s), (filter (complement f) s) ]" [f s] [(filter f s) (filter (complement f) s)]) If you do care about the 2 passes you can always fall back to imperative code + transients like so: (defn separate [pred coll] ;;should be really fast as it only does a single pass (let [[yes no :as both] (list (transient []) (transient []))] (doseq [x coll] (if (pred x) (conj! yes x) (conj! no x))) (mapv persistent! both))) Jim On 04/04/13 13:16, Christian Romney wrote: Hi all, I was wondering if something in core (or new contrib) like this exists already... (defn segregate "Takes a predicate, p, and a collection, coll, and separates the items in coll into matching and non-matching subsets. Like Scheme or Ruby's partition." [p coll] (loop [s coll y [] n []] (if (empty? s) [y n] (if (p (first s)) (recur (rest s) (conj y (first s)) n) (recur (rest s) y (conj n (first s))) (let [[odds evens] (segregate odd? (range 1 11))] (println evens)) In Scheme (and Ruby) this function is partition, which is quite different from /partition(-all|-by)?/ in Clojure: #lang racket (let-values [[(odds evens) (partition odd? (range 1 11))]] (display evens)) If not, I have two follow-up questions. 1) Is there a better way to write segregate 2) Is this useful enough to consider adding to core? TIA, and my apologies for the newbie question. :) (Gist version if you prefer: https://gist.github.com/xmlblog/5309853) -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out. -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Analog to Scheme's partition in Clojure?
Christian Romney writes: Hey Christian, > (defn segregate > "Takes a predicate, p, and a collection, coll, and separates the items in > coll >into matching and non-matching subsets. Like Scheme or Ruby's partition." > [p coll] > (loop [s coll y [] n []] > (if (empty? s) [y n] > (if (p (first s)) > (recur (rest s) (conj y (first s)) n) > (recur (rest s) y (conj n (first s))) > > If not, I have two follow-up questions. No, I think there's nothing like that in core. But I also feel a need for that, since I also frequently do (let [e (filter even? coll) o (remove even? coll)] ...) which is nearly equivalent, except that it's lazy (i.e., e and o are lazy seqs) where yours is eager (returns two vectors). group-by in core is also eager. > 1) Is there a better way to write segregate This would work and also returns a vector of two lazy seqs: (def segregate (juxt filter remove)) Then you can do (let [[e o] (segregate even? coll)] ...) exactly as with your version. > 2) Is this useful enough to consider adding to core? IMHO, yes, but it should return a vector of 2 lazy seqs. The eager case is captured enough by group-by, IMHO. However, the what's bad with the juxt approach above is that the collection is iterated twice. If somebody comes up with a version that returns a vector of two lazy seqs and which iterates the input collection only once, she'd get my warmest thank you, and my vote for putting it into core. Bye, Tassilo -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Analog to Scheme's partition in Clojure?
On Thu, Apr 4, 2013 at 8:06 AM, David Powell wrote: > You could use the long-form of map destructuring: > > (let [{odd true even false} (group-by odd? (range 1 10))] > (println odd) > (println even)) I do this frequently. Do be careful that if your "predicate" doesn't return actual booleans, you may want to coerce with (boolean ...). -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Analog to Scheme's partition in Clojure?
> I thought about map destructuring but I don't think it works with boolean > keys. I think this is good enough though: > You could use the long-form of map destructuring: (let [{odd true even false} (group-by odd? (range 1 10))] (println odd) (println even)) -- Dave -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Analog to Scheme's partition in Clojure?
On Thursday, April 4, 2013 8:25:32 AM UTC-4, Jonathan Fischer Friberg wrote: > I think group-by can do what you want (and more); > Hi Jonathan, Thanks for the reply. I had looked at group-by, and hastily dismissed it due to lack of imagination. This would work, though it isn't as "pretty". (let [is-odd (group-by odd? (range 1 11))] (println (is-odd false))) I thought about map destructuring but I don't think it works with boolean keys. I think this is good enough though: (let [is-odd (group-by odd? (range 1 11)) evens (is-odd false) odds (is-odd true)] (println evens)) Thanks again -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Re: Analog to Scheme's partition in Clojure?
I think group-by can do what you want (and more); http://clojuredocs.org/clojure_core/clojure.core/group-by Jonathan On Thu, Apr 4, 2013 at 2:16 PM, Christian Romney wrote: > Hi all, > > I was wondering if something in core (or new contrib) like this exists > already... > > (defn segregate > "Takes a predicate, p, and a collection, coll, and separates the items in > coll >into matching and non-matching subsets. Like Scheme or Ruby's partition." > [p coll] > (loop [s coll y [] n []] > (if (empty? s) [y n] > (if (p (first s)) > (recur (rest s) (conj y (first s)) n) > (recur (rest s) y (conj n (first s))) > > > (let [[odds evens] (segregate odd? (range 1 11))] > (println evens)) > > In Scheme (and Ruby) this function is partition, which is quite different > from /partition(-all|-by)?/ in Clojure: > > #lang racket > > (let-values [[(odds evens) (partition odd? (range 1 11))]] > (display evens)) > > If not, I have two follow-up questions. > > 1) Is there a better way to write segregate > 2) Is this useful enough to consider adding to core? > > TIA, and my apologies for the newbie question. :) > > (Gist version if you prefer: https://gist.github.com/xmlblog/5309853) > > -- > -- > 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 > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/groups/opt_out. > > > -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Analog to Scheme's partition in Clojure?
Hi all, I was wondering if something in core (or new contrib) like this exists already... (defn segregate "Takes a predicate, p, and a collection, coll, and separates the items in coll into matching and non-matching subsets. Like Scheme or Ruby's partition." [p coll] (loop [s coll y [] n []] (if (empty? s) [y n] (if (p (first s)) (recur (rest s) (conj y (first s)) n) (recur (rest s) y (conj n (first s))) (let [[odds evens] (segregate odd? (range 1 11))] (println evens)) In Scheme (and Ruby) this function is partition, which is quite different from /partition(-all|-by)?/ in Clojure: #lang racket (let-values [[(odds evens) (partition odd? (range 1 11))]] (display evens)) If not, I have two follow-up questions. 1) Is there a better way to write segregate 2) Is this useful enough to consider adding to core? TIA, and my apologies for the newbie question. :) (Gist version if you prefer: https://gist.github.com/xmlblog/5309853) -- -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.