On Mon, Mar 14, 2011 at 4:13 PM, Tassilo Horn <tass...@member.fsf.org> wrote:
> Hi all,
>
> I've implemented IEditableCollection support for ninjudd's
> PersistentOrderedSet.  But when using that, my application delivered
> wrong results.  See <87hbb6c4qf....@member.fsf.org> and follow-ups.
>
> I was able to track it down to the strangeness in the subject:
>
>  (.contains (transient (hash-set)) foo)
>
> returns true for any object foo, that is, the empty transient hash-set
> contains everything.
>
> The above clojure code is equivalent to this java code, which I used in
> the PersistentOrderedSet extension:
>
>  ((ITransientSet) PersistentHashSet.EMPTY.asTransient()).contains(o)
>
> For now, I worked around this strange behavior by checking the count()
> of the TransientHashSet backing my TransientOrderedSet implementation in
> addition to contains().
>
> But anyway: Is that behavior intended and facilitated internally
> somehow?  If so, is there some documentation about the rationale?
>
> Bye,
> Tassilo

At first blush, the answer appears to be "no".

Here is APersistentSet.contains:

public boolean contains(Object key){
        return impl.containsKey(key);
}

Here is ATransientSet.contains:

public boolean contains(Object key) {
        return this != impl.valAt(key, this);
}

This should probably use a sentinel; it's possible to put a transient
map into itself, at least in principle. But the real problem:


user=> (.valAt (.asTransient clojure.lang.PersistentHashMap/EMPTY) 1 42)
nil

Oops! This should have returned 42, not nil!

The actual error is on line 278 of PersistentHashMap.java:


Object doValAt(Object key, Object notFound) {
        if (key == null)
                if (hasNull)
                        return nullValue;
                else
                        return notFound;
        if (root == null)
                return null;
        return root.find(0, Util.hash(key), key, notFound);
}

This obviously should say

        if (root == null)
                return notFound;

!!!

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