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-19 Thread Greg D
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?

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

2009-06-10 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 are subscribed to the Google
Groups Clojure group.
To post to this 

Re: Thoughts on bags?

2009-06-10 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-10 Thread Rich Hickey



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?

2009-06-09 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-09 Thread AndrewC.

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?

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 Kevin Downey

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?

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



Thoughts on bags?

2009-06-08 Thread Richard Newman

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?

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

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