Re: Analog to Scheme's partition in Clojure?

2013-04-05 Thread Tassilo Horn
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?

2013-04-04 Thread Ben Wolfson
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?

2013-04-04 Thread Jim - FooBar();
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?

2013-04-04 Thread Christian Romney
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?

2013-04-04 Thread Jim - FooBar();
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?

2013-04-04 Thread Tassilo Horn
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?

2013-04-04 Thread John D. Hume
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?

2013-04-04 Thread David Powell
> 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?

2013-04-04 Thread Christian Romney
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?

2013-04-04 Thread Jonathan Fischer Friberg
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?

2013-04-04 Thread Christian Romney
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.