There are some subtle exceptions (e.g. don't mix Java mutable maps and
Clojure immutable maps), but if they are all immutable, and you don't mix
floats and doubles in there anywhere, and you don't use Double/NaN 'values'
anywhere, and probably a couple other minor caveats I am forgetting right
now, you cannot put more than one map with the same key/value pairs into a
set more than once, because they are equal to each other:

user=> (def s1 #{})
#'user/s1
user=> (def s2 (conj s1 {:a 1 :b 2 :c [3 4]}))
#'user/s2
user=> s2
#{{:c [3 4], :b 2, :a 1}}
user=> (def s3 (conj s2 {:c [3 4] :a 1 :b 2}))
#'user/s3
user=> s3
#{{:c [3 4], :b 2, :a 1}}

Andy


On Mon, Apr 6, 2015 at 1:56 PM, Simon Brooke <still...@googlemail.com>
wrote:

> Sorry to be so slow getting back. Because they are maps, and a set can
> contain many maps which contain identical key value pairs - I assume
> because although they do indeed have identical key value pairs they are
> nevertheless not the same map.
>
> On Tuesday, 24 March 2015 21:55:05 UTC, Ben wrote:
>>
>> why not just accumulate the interested customers in a set rather than a
>> seq in the first place?
>>
>> On Tue, Mar 24, 2015 at 2:50 PM, Simon Brooke <stil...@googlemail.com>
>> wrote:
>>
>>> I'm rewriting a very odd e-commerce website I first wrote in 1996, for a
>>> friend.
>>>
>>> The website features categories, which are supposed to be arranged into
>>> an acyclic directed graph (actually there are currently cycles in the
>>> graph, but there shouldn't be, and that is not the problem I'm trying to
>>> solve here; assume there are not). Customers can register interest in a
>>> category or in several categories. When an item is added to the site, we
>>> want to email every customer who may be interested in that item; which is
>>> to say
>>>
>>> customers who are interested in the category to which the item has been
>>> added, and
>>> customers who are interested in the parent of that category, and
>>> so on recursively to the root of the graph.
>>>
>>> Now, I can recurse up the graph asking each category in turn for the
>>> customers interested in it; and by concatenating the lists, arrive at one
>>> list of all the interested customers. The problem is that if one customer
>>> has registered interest in both a category and its parent, he will appear
>>> on the composite list twice. I need to construct from this a list of
>>> records in which each customer appears only once, otherwise they'll receive
>>> duplicate emails, which no-one likes.
>>>
>>> My solution, which I give below, is to recurse across the composite list
>>> constructing a map whose keys are email addresses and whose values are the
>>> customer records as maps; and then to take the values of that map. It
>>> works, but it doesn't feel like idiomatic clojure:
>>>
>>> (defn map-by-key
>>>   "From this `list-of-maps`, produce a map keyed on the values for this
>>> `key`"
>>>   [list-of-maps key]
>>>   (if (empty? list-of-maps) {}
>>>     (let [record (first list-of-maps)]
>>>       (merge {(record key) record} (map-by-key (rest list-of-maps)
>>> key)))))
>>>
>>>
>>> (defn interested-customers
>>>   "Return a list of the customers interested in the category with this
>>>    `category-id`. Recurses up the tree of categories; `path` is passed to
>>>    protect against cycles in the tree (which shouldn't be there by are
>>>    not impossible)"
>>>   ([category-id]
>>>    (vals (map-by-key (interested-customers category-id #{}) :email)))
>>>   ([category-id path]
>>>    (if (contains? path category-id) ()
>>>     (let
>>>       [id (if (integer? category-id) category-id
>>>             (Integer/valueOf (str category-id)))
>>>        category (categories/fetch id)
>>>        parent (:parent category)
>>>        upstream (if (not (nil? parent)) (interested-customers parent
>>> (conj path id)) ())
>>>        interested (select schema/customer
>>>                           (with schema/category
>>>                             (where {:id id})))]
>>>       (concat interested upstream)))))
>>>
>>> Can anyone re-express that in a more idiomatic form?
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>
>>
>> --
>> 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/d/optout.
>

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

Reply via email to