Re: Thoughts on bags?
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?
Added link missing in previous post. A simple multiset/bag implementation for Clojurehttps://github.com/achim/multiset -- 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?
While searching for MultiSet or Bag resources, I found this implementation by Achim Passen at: A simple multiset/bag implementation for Clojurehttps://github.com/achim/multiset . 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 Structureshttp://clojure.org/data_structures#hash : (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?
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 are subscribed to the Google Groups Clojure group. To post to this
Re: Thoughts on bags?
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?
On Jun 10, 2:09 am, Richard Newman holyg...@gmail.com 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 under-charge Foocorp! You get the same result if you omit the :id from the projection vector. While I thinks bags and multimaps would be nice additions to the core
Re: Thoughts on bags?
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?
On Jun 9, 7:49 am, Konrad Hinsen konrad.hin...@laposte.net 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?
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?
On Tue, Jun 9, 2009 at 7:49 PM, Richard Newmanholyg...@gmail.com 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?
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 -~--~~~~--~~--~--~---
Thoughts on bags?
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 -~--~~~~--~~--~--~---
Re: Thoughts on bags?
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 holyg...@gmail.com 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 -~--~~~~--~~--~--~---
Re: Thoughts on bags?
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 -~--~~~~--~~--~--~---