On 19 June 2010 18:59, Albert Cardona <sapri...@gmail.com> wrote:
> 1. How come APersistentMap$KeySet doesn't implement IPersistentSet?

Beyond what Rob has already written above, keys works with
APersistentMap$KeySeq (note the "q" at the end), not
APersistentMap$KeySet. To get at the latter, use (.keySet {:a 1 :b
2}); you'll get back a java.util.Set of two entries, :a and :b. This
is mainly an interop feature, I believe (meant to make it easier for
non-Clojure code on the JVM to read Clojure data structures directly).

clojure.set/intersection knows how to handle java.util.Set instances,
though in this case, using (comp set keys) -- that is, normally, (set
(keys ...)) -- is the more usual and overall more sensible way to go.

> 2. I can't get clojure.set/project to work.

clojure.set/project is meant to implement the projection operator of
[Relational algebra](http://en.wikipedia.org/wiki/Relational_algebra).

The representation of relations assumed here is a "collection of
tuples", which makes sense: the mathematical definition of a relation
-- the one used in relational algebra -- is "a set of tuples". The
tuples are here represented as maps. Of course in a mathematical
relation all tuples have the same "format"; in Clojure, if some of the
maps happen to be missing some of the keys present in some of the
other maps, the overall semantics are very much (if not exactly) as if
they had those keys bound to nil (as the usual Clojure semantics for
maps would imply).

Now the projection operator takes a relation and throws out some of
its attributes (or some of the columns if you visualise it as a table;
or if you think of a set of tuples, it removes some axes from all the
tuples). The result is still a relation, i.e. a set, meaning in
particular that there are no duplicates:

(clojure.set/project #{{:foo 1 :bar 2} {:foo 1 :bar 3}} [:foo])

returns #{{:foo 1}}, because once we throw out the :bars, the two
tuples from the input relation become indistinguishable on the basis
of the remaining :foo attribute and "blend together" into just one
tuple in the output relation.

An example where the projection is larger:

(clojure.set/project #{{:foo 1 :bar 2} {:foo 2 :quux 3}} [:foo])
; => #{{:foo 1} {:foo 2}}

So, that's how it's supposed to work. Your final example should
perhaps fail more gracefully -- the first argument to
clojure.set/project cannot be a map (which is by definition a
collection of map entries and not of maps, as required here). As
things stand, it gives a weird result due to clojure.set/project using
select-keys, which in turn uses clojure.lang.RT/find, which happens to
return nils when it's called with an argument which makes no sense (in
addition to returning nil when the argument does make sense -- i.e. is
a map -- but the given key is not found).

Sincerely,
Michał

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

Reply via email to