Re: Thoughts on bags?

2014-04-19 Thread Greg D
Added link missing in previous post.

A simple multiset/bag implementation for 
Clojure

-- 
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/d/optout.


Re: Thoughts on bags?

2014-04-19 Thread Greg D
While searching for MultiSet or Bag resources, I found this implementation 
by Achim Passen at: A simple multiset/bag implementation for Clojure.

However, I found I could meet my needs by adding functions to treat 
vectors, or other collection types, as unordered. These can then be used 
directly, or in the definition of your own specialized types.

For the hash, from Clojure Data Structures:

(defn hash-unordered [collection]
  (-> (reduce unchecked-add-int 0 (map hash collection))
  (mix-collection-hash (count collection


For equality:
(defn equals-unordered [coll-a coll-b]
  "Treat collections as unordered for 1st level of comparison."
  (or (identical? coll-a coll-b)
  (and (empty? coll-a) (empty? coll-b))
  (and (= (hash-unordered coll-a) (hash-unordered coll-b))
   (let [set-a (set coll-a)
 set-b (set coll-b)]
 (and (= set-a set-b)
  (loop [[item & items] (seq set-a)]
(let [finder #(= item %)
  found-a (filter finder coll-a)
  found-b (filter finder coll-b)]
  (if (not= (count found-a) (count found-b))
false
(if (empty? items)
  true
  (recur items))

Neither Achim's deftype, nor the above, is likely as efficient as 
implementation as a core collection MultiSet.

The attached file has a trivial implementation of a deftype showing the 
functions in use. It defines a shopping cart where the items are kept on a 
vector, which is treated as an unordered collection. A transcript of 
playing with the shopping cart follows:

user=> (load-file "shopping_cart.clj")
#'example.multi-set/make-shopping-cart
user=> (use 'example.multi-set)
nil
user=> (def cart0 (make-shopping-cart 'carrots 'beans 'eggs))
#'user/cart0
user=> cart0
(make-shopping-cart carrots beans eggs)
user=> (def cart1 (make-shopping-cart 'eggs 'carrots 'beans))
#'user/cart1
user=> cart1
(make-shopping-cart eggs carrots beans)
user=> (def cart2 (make-shopping-cart 'ham 'eggs 'carrots 'beans))
#'user/cart2
user=> cart2
(make-shopping-cart ham eggs carrots beans)
user=> (= cart0 cart1)
true
user=> (= cart1 cart2)
false  

Greg

-- 
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/d/optout.


shopping_cart.clj
Description: Binary data


Re: Thoughts on bags?

2014-04-17 Thread Greg D
While searching for MultiSet or Bag resources, I found this implementation 
by Achim Passen at: A simple multiset/bag implementation for 
Clojure
.

However, I found I could meet my needs by adding functions to treat 
vectors, or other collection types, as unordered.

For the hash, from Clojure Data 
Structures
:

(defn hash-unordered [collection]
  (-> (reduce unchecked-add-int 0 (map hash collection))
  (mix-collection-hash (count collection


For equality:
(defn equals-unordered [coll-a coll-b]
  "Treat collections as unordered for 1st level of comparison."
  (or (identical? coll-a coll-b)
  (and (empty? coll-a) (empty? coll-b))
  (let [set-a (set coll-a)
set-b (set coll-b)]
(and (= set-a set-b)
 (loop [[item & items] (seq set-a)]
   (let [finder #(= item %)
 found-a (filter finder coll-a)
 found-b (filter finder coll-b)]
 (if (not= (count found-a) (count found-b))
   false
   (if (empty? items)
 true
 (recur items)

Neither Achim's deftype, nor the above, is likely as efficient as a core 
collection MultiSet. In the meantime, I hope these observations are useful.

Greg

-- 
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/d/optout.


Re: Thoughts on bags?

2009-06-10 Thread Rich Hickey



On Jun 10, 2:09 am, Richard Newman  wrote:
> > I am very fond of the relational functions in Clojure. That was one of
> > the first things that started winning me over actually.
>
> Indeed, they're very nice to have!
>
> > Forgive me if this is an obvious question, but what exactly is the
> > disadvantage of the add-an-id approach?
>
> It's largely aesthetic for me: I don't like the idea of having to
> generate some identifier and decorate my data with it. From my
> perspective it's a hack to turn a set into a multiset, which is the
> concept I'm really working with (an unordered collection which
> includes duplicates). One could argue that choosing a name for the ID
> is not obviously easy, and that this is an approach that only works
> well for maps/structs, but those problems don't apply in my case, so I
> won't argue those points!
>
> I haven't done any timing to determine if it's an expensive hack: this
> is not time-critical code, so it doesn't matter much to me. For that
> reason I'll probably stick with this approach, albeit well-commented
> to explain to my future self why I'm temporarily introducing an
> otherwise-unused ID!
>
> I raised this whole issue not because I can't work around it, but
> because I like to use the right tool for the job if it exists, and
> maybe other people already built that tool. Who knows? perhaps Rich
> has been considering spending an afternoon adding multisets to core,
> and this is additional motivation. After all, we now have sorted-sets,
> which is the other axis of set-hood...
>
> > Or, another way, what would be
> > substantially better about having multisets over just doing what
> > you're doing? My understanding of relational theory and SQL (thanks
> > largely to Joe Celko's books) makes me suspicious of needing
> > cardinality—it sounds a lot like wanting access to the physical
> > ordering on disk. Then again, a lot of my database tables wind up with
> > a sort-order column or an auto-incrementing ID, I admit.
>
> It depends on how "pure" your experience with relational algebra is :)
>
> I've spent a lot of time with SPARQL, the RDF query language. It's
> relational (much like SQL for the web), but it preserves cardinality
> by default, but not ordering. (It has REDUCED and DISTINCT keywords to
> discard duplicates if desired or permitted.)
>
> Some people think preserving cardinality is an odd choice, given that
> RDF is defined in terms of sets, not bags, but it has its uses.
>
> Modeling event-like things (charges, in my case) in a pure relational
> system -- one with set semantics -- typically requires the addition of
> two things: a unique identifier to preserve otherwise-identical
> events; and some ordering attribute, to preserve sequentiality in an
> unordered system. Removing the "set-ness" (cardinality, un-
> orderedness, or both) is another way to resolve the impedance mismatch.
>
> > Of course, just because it violates relational theory doesn't mean it
> > wouldn't be a great addition to the language. I'm curious.
>
> > Would you mind sharing the code with the error for the calculation
> > you're doing?
>
> I'm afraid I can't share the exact code, but the simplified relational
> part is something like:
>
> (use 'clojure.set)
>
> (defn example-charges
>"Take a relation between charge and identifier, and a relation
> between
> identifier and client, and sum the charges for each client."
>[charges-rel clients]
>
>;; 5. Produce a sum charge for each client in a single map.
>;; No need to apply merge-with: the index has unique keys.
>(into {}
>  (map
>;; 4. Turn the index into a numeric sum for each client.
>(fn [[k v]]
>  [(:client k)
>   (reduce + (map :charge v))])
>
>(index
>  (project
>;; 1. Note that any identifiers not in the clients relation
> will
>;; simply disappear at this point.
>(join
>  charges-rel
>  clients)
>
>;; 2. Include :id in the projection to prevent set semantics.
>[:client :charge :id])
>
>  ;; 3. Now index from client to the projected relations.
>  #{:client}
>
> E.g.,
>
> (example-charges
>#{{:charge 10 :identifier "12345abcdef" :id 0}
>  {:charge 10 :identifier "67890ghijkl" :id 1}
>  {:charge 15 :identifier "12345poiuyt" :id 2}}
>#{{:identifier "12345abcdef" :client "Foocorp"}
>  {:identifier "67890ghijkl" :client "Foocorp"}
>  {:identifier "12345poiuyt" :client "Barcorp"}})
>
> => {"Foocorp" 20, "Barcorp" 15}
>
> Omit the :id and we get this:
>
> (example-charges
>#{{:charge 10 :identifier "12345abcdef"}
>  {:charge 10 :identifier "67890ghijkl"}
>  {:charge 15 :identifier "12345poiuyt"}}
>#{{:identifier "12345abcdef" :client "Foocorp"}
>  {:identifier "67890ghijkl" :client "Foocorp"}
>  {:identifier "12345poiuyt" :client "Barcorp"}})
>
> => {"Barcorp" 15, "Foocorp" 10}
>
> Oops! We're going to

Re: Thoughts on bags?

2009-06-09 Thread Konrad Hinsen

On 10.06.2009, at 04:49, Richard Newman wrote:

> The cardinality tracking has been (necessarily, I understand) lifted
> into the explicit contents of the data structure, so applications
> which call Clojure code that performs core operations (not your
> generic versions) on those structures will not work.

Indeed. But there is no way around that. Standard Clojure functions  
have no dispatch mechanism at all, so you can't make a function work  
with different data types, unless the function happens to access the  
data only through a Java interface that you could implement in some  
other Java class.

> So far as I understand it, to get 'native' multisets would require an
> implementation of IPersistentCollection, or perhaps IPersistentSet
> itself (if the contract of the interface doesn't impose set
> semantics), and ideally some Clojure surface syntax.

Yes. It will also very probably require changes to the set  
operations, meaning either a patch to clojure.core or an additional  
set of functions that live in some other namespace.

Konrad.

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



Re: Thoughts on bags?

2009-06-09 Thread Richard Newman

> I am very fond of the relational functions in Clojure. That was one of
> the first things that started winning me over actually.

Indeed, they're very nice to have!

> Forgive me if this is an obvious question, but what exactly is the
> disadvantage of the add-an-id approach?

It's largely aesthetic for me: I don't like the idea of having to  
generate some identifier and decorate my data with it. From my  
perspective it's a hack to turn a set into a multiset, which is the  
concept I'm really working with (an unordered collection which  
includes duplicates). One could argue that choosing a name for the ID  
is not obviously easy, and that this is an approach that only works  
well for maps/structs, but those problems don't apply in my case, so I  
won't argue those points!

I haven't done any timing to determine if it's an expensive hack: this  
is not time-critical code, so it doesn't matter much to me. For that  
reason I'll probably stick with this approach, albeit well-commented  
to explain to my future self why I'm temporarily introducing an  
otherwise-unused ID!

I raised this whole issue not because I can't work around it, but  
because I like to use the right tool for the job if it exists, and  
maybe other people already built that tool. Who knows? perhaps Rich  
has been considering spending an afternoon adding multisets to core,  
and this is additional motivation. After all, we now have sorted-sets,  
which is the other axis of set-hood...


> Or, another way, what would be
> substantially better about having multisets over just doing what
> you're doing? My understanding of relational theory and SQL (thanks
> largely to Joe Celko's books) makes me suspicious of needing
> cardinality—it sounds a lot like wanting access to the physical
> ordering on disk. Then again, a lot of my database tables wind up with
> a sort-order column or an auto-incrementing ID, I admit.

It depends on how "pure" your experience with relational algebra is :)

I've spent a lot of time with SPARQL, the RDF query language. It's  
relational (much like SQL for the web), but it preserves cardinality  
by default, but not ordering. (It has REDUCED and DISTINCT keywords to  
discard duplicates if desired or permitted.)

Some people think preserving cardinality is an odd choice, given that  
RDF is defined in terms of sets, not bags, but it has its uses.

Modeling event-like things (charges, in my case) in a pure relational  
system -- one with set semantics -- typically requires the addition of  
two things: a unique identifier to preserve otherwise-identical  
events; and some ordering attribute, to preserve sequentiality in an  
unordered system. Removing the "set-ness" (cardinality, un- 
orderedness, or both) is another way to resolve the impedance mismatch.


> Of course, just because it violates relational theory doesn't mean it
> wouldn't be a great addition to the language. I'm curious.
>
> Would you mind sharing the code with the error for the calculation
> you're doing?

I'm afraid I can't share the exact code, but the simplified relational  
part is something like:

(use 'clojure.set)

(defn example-charges
   "Take a relation between charge and identifier, and a relation  
between
identifier and client, and sum the charges for each client."
   [charges-rel clients]

   ;; 5. Produce a sum charge for each client in a single map.
   ;; No need to apply merge-with: the index has unique keys.
   (into {}
 (map
   ;; 4. Turn the index into a numeric sum for each client.
   (fn [[k v]]
 [(:client k)
  (reduce + (map :charge v))])

   (index
 (project
   ;; 1. Note that any identifiers not in the clients relation  
will
   ;; simply disappear at this point.
   (join
 charges-rel
 clients)

   ;; 2. Include :id in the projection to prevent set semantics.
   [:client :charge :id])

 ;; 3. Now index from client to the projected relations.
 #{:client}


E.g.,

(example-charges
   #{{:charge 10 :identifier "12345abcdef" :id 0}
 {:charge 10 :identifier "67890ghijkl" :id 1}
 {:charge 15 :identifier "12345poiuyt" :id 2}}
   #{{:identifier "12345abcdef" :client "Foocorp"}
 {:identifier "67890ghijkl" :client "Foocorp"}
 {:identifier "12345poiuyt" :client "Barcorp"}})

=> {"Foocorp" 20, "Barcorp" 15}


Omit the :id and we get this:

(example-charges
   #{{:charge 10 :identifier "12345abcdef"}
 {:charge 10 :identifier "67890ghijkl"}
 {:charge 15 :identifier "12345poiuyt"}}
   #{{:identifier "12345abcdef" :client "Foocorp"}
 {:identifier "67890ghijkl" :client "Foocorp"}
 {:identifier "12345poiuyt" :client "Barcorp"}})

=> {"Barcorp" 15, "Foocorp" 10}

Oops! We're going to under-charge Foocorp!

You get the same result if you omit the :id from the projection vector.

Thanks,

-R
--~--~-~--~~~---~--~~
You received this message because you 

Re: Thoughts on bags?

2009-06-09 Thread Daniel Lyons


On Jun 9, 2009, at 8:49 PM, Richard Newman wrote:

> For now, as I'm storing maps in my sets -- I'm doing relational stuff,
> after all -- I just add an :id entry in each map, filled by (iterate
> inc 0). Functionally the same as a multiset, so long as I ignore
> the :id 'column'...


I am very fond of the relational functions in Clojure. That was one of  
the first things that started winning me over actually.

Forgive me if this is an obvious question, but what exactly is the  
disadvantage of the add-an-id approach? Or, another way, what would be  
substantially better about having multisets over just doing what  
you're doing? My understanding of relational theory and SQL (thanks  
largely to Joe Celko's books) makes me suspicious of needing  
cardinality—it sounds a lot like wanting access to the physical  
ordering on disk. Then again, a lot of my database tables wind up with  
a sort-order column or an auto-incrementing ID, I admit.

Of course, just because it violates relational theory doesn't mean it  
wouldn't be a great addition to the language. I'm curious.

Would you mind sharing the code with the error for the calculation  
you're doing?

—
Daniel Lyons
http://www.storytotell.org -- Tell It!


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



Re: Thoughts on bags?

2009-06-09 Thread Kevin Downey

On Tue, Jun 9, 2009 at 7:49 PM, Richard Newman wrote:
>
> Thanks, Konrad and Andrew, for chipping in!
>
>>> There's an outline of an implementation of multisets (I think that's
>>> the same as your bags) at:
>>>
>>>        http://code.google.com/p/clojure-contrib/source/browse/trunk/src/
>>> clojure/contrib/types/examples.clj
>
> Thanks for the pointer.
>
> I apologize for the negativity, but these don't seem "first class" --
> that is, I can't treat them as I would sets:
>
> user=> (map identity #{:a :b :c})
> (:a :c :b)
> user=> (map identity (gc/conj (multiset {}) :a :b :c)))
> ([:c 1] [:b 1] [:a 1])

all that needs to happen is for multiset to provide it's own seq, like
it supplies it's own conj. seq would strip  whatever information out.
you would need to call it explicitly on the multiset before passing it
to functions which call seq internally (map, filter, etc).

> The cardinality tracking has been (necessarily, I understand) lifted
> into the explicit contents of the data structure, so applications
> which call Clojure code that performs core operations (not your
> generic versions) on those structures will not work.
>
> Consequently, I couldn't use these with clojure.set's relational
> operations, for example:
>
> user=> (clojure.set/join
>          #{{:name "John" :id 4} {:name "John" :id 3}}
>          #{{:age 32 :id 4} {:age 19 :id 3}})
> #{{:age 19, :name "John", :id 3} {:age 32, :name "John", :id 4}}
>
> user=> (clojure.set/join
>          (gc/conj (multiset {}) {:name "John" :id 4} {:name
> "John" :id 3})
>          (gc/conj (multiset {}) {:age 32 :id 4} {:age 19 :id 3}))
> java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot
> be cast to java.util.Map$Entry (NO_SOURCE_FILE:0)
>
> So far as I understand it, to get 'native' multisets would require an
> implementation of IPersistentCollection, or perhaps IPersistentSet
> itself (if the contract of the interface doesn't impose set
> semantics), and ideally some Clojure surface syntax.
>
> PersistentTreeSet doesn't look too scary, so perhaps I'll dive in...
> more fun than my paid work, after all :)
>
>
>> Google Collections has Multisets - and they have an immutable
>> implementation.
>>
>> http://code.google.com/p/google-collections/
>
> Hmm, interesting. Not sure how their builder-based approach would fit
> in.
>
> For now, as I'm storing maps in my sets -- I'm doing relational stuff,
> after all -- I just add an :id entry in each map, filled by (iterate
> inc 0). Functionally the same as a multiset, so long as I ignore
> the :id 'column'...
>
> >
>



-- 
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?

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



Re: Thoughts on bags?

2009-06-09 Thread Richard Newman

Thanks, Konrad and Andrew, for chipping in!

>> There's an outline of an implementation of multisets (I think that's
>> the same as your bags) at:
>>
>>http://code.google.com/p/clojure-contrib/source/browse/trunk/src/
>> clojure/contrib/types/examples.clj

Thanks for the pointer.

I apologize for the negativity, but these don't seem "first class" --  
that is, I can't treat them as I would sets:

user=> (map identity #{:a :b :c})
(:a :c :b)
user=> (map identity (gc/conj (multiset {}) :a :b :c)))
([:c 1] [:b 1] [:a 1])

The cardinality tracking has been (necessarily, I understand) lifted  
into the explicit contents of the data structure, so applications  
which call Clojure code that performs core operations (not your  
generic versions) on those structures will not work.

Consequently, I couldn't use these with clojure.set's relational  
operations, for example:

user=> (clojure.set/join
  #{{:name "John" :id 4} {:name "John" :id 3}}
  #{{:age 32 :id 4} {:age 19 :id 3}})
#{{:age 19, :name "John", :id 3} {:age 32, :name "John", :id 4}}

user=> (clojure.set/join
  (gc/conj (multiset {}) {:name "John" :id 4} {:name  
"John" :id 3})
  (gc/conj (multiset {}) {:age 32 :id 4} {:age 19 :id 3}))
java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot  
be cast to java.util.Map$Entry (NO_SOURCE_FILE:0)

So far as I understand it, to get 'native' multisets would require an  
implementation of IPersistentCollection, or perhaps IPersistentSet  
itself (if the contract of the interface doesn't impose set  
semantics), and ideally some Clojure surface syntax.

PersistentTreeSet doesn't look too scary, so perhaps I'll dive in...  
more fun than my paid work, after all :)


> Google Collections has Multisets - and they have an immutable
> implementation.
>
> http://code.google.com/p/google-collections/

Hmm, interesting. Not sure how their builder-based approach would fit  
in.

For now, as I'm storing maps in my sets -- I'm doing relational stuff,  
after all -- I just add an :id entry in each map, filled by (iterate  
inc 0). Functionally the same as a multiset, so long as I ignore  
the :id 'column'...

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



Re: Thoughts on bags?

2009-06-09 Thread AndrewC.

On Jun 9, 7:49 am, Konrad Hinsen  wrote:
> On 09.06.2009, at 07:31, Richard Newman wrote:
>
> > Has there been any thinking about supporting a 'bag' sibling of 'set',
> > and allowing it to be passed correctly through the relational
> > operators? Right now I have a choice between rephrasing my code in  
> > non-
> > relational terms, or adding a unique value to each item to thwart the
> > distinctness semantics. I can't help but think that other people will
> > also encounter this.
>
> There's an outline of an implementation of multisets (I think that's  
> the same as your bags) at:
>
>        http://code.google.com/p/clojure-contrib/source/browse/trunk/src/
> clojure/contrib/types/examples.clj

Google Collections has Multisets - and they have an immutable
implementation.

http://code.google.com/p/google-collections/
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



Re: Thoughts on bags?

2009-06-08 Thread Konrad Hinsen

On 09.06.2009, at 07:31, Richard Newman wrote:

> Has there been any thinking about supporting a 'bag' sibling of 'set',
> and allowing it to be passed correctly through the relational
> operators? Right now I have a choice between rephrasing my code in  
> non-
> relational terms, or adding a unique value to each item to thwart the
> distinctness semantics. I can't help but think that other people will
> also encounter this.

There's an outline of an implementation of multisets (I think that's  
the same as your bags) at:

http://code.google.com/p/clojure-contrib/source/browse/trunk/src/ 
clojure/contrib/types/examples.clj

A full implementation could be built using the same methods and  
tools, and you'd have set operations that work equally with sets and  
multisets, even permitting mixing the two. The price to pay is the  
execution time overhead of multimethod dispatch.

Konrad.


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



Re: Thoughts on bags?

2009-06-08 Thread Richard Newman

> I think I know what you mean by a "bag", but I'm not quite sure.  How
> does a bag compare to a set, vector and/or list?

A bag is also known as a multiset: it's an unordered collection in  
which an item can appear more than once. Think of a set without the  
distinctness.

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



Re: Thoughts on bags?

2009-06-08 Thread Sean Devlin

I think I know what you mean by a "bag", but I'm not quite sure.  How
does a bag compare to a set, vector and/or list?

On Jun 9, 1:31 am, Richard Newman  wrote:
> The relational operations work on sets. That's often useful, but there  
> are situations in which preserving cardinality is more useful. One  
> such situation bit me today -- I did some relational operations on  
> some spreadsheet-esque data, much as I would in SQL or SPARQL, finally  
> projecting to the two columns I cared about before adding up some  
> numbers.
>
> The numbers didn't total correctly. A few minutes of reading my code  
> narrowed it down to the projection, which of course outputs a set,  
> discarding some of my inputs.
>
> Has there been any thinking about supporting a 'bag' sibling of 'set',  
> and allowing it to be passed correctly through the relational  
> operators? Right now I have a choice between rephrasing my code in non-
> relational terms, or adding a unique value to each item to thwart the  
> distinctness semantics. I can't help but think that other people will  
> also encounter this.
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---