Skip to content

TreeMap#split appears broken #4

Description

@shajra

I wrote the following test for TreeMap#split and got some unexpected behavior: https://gist.github.com/996438.

It appears the "lesser" and "greater" value sets are being reduced to singleton sets. I looked at the implementation

public P3<Set<V>, Option<V>, Set<V>> split(final K k) {
    final F<Set<P2<K, Option<V>>>, Set<V>> getSome = Option.<V>fromSome().o(P2.<K, Option<V>>__2())
        .mapSet(tree.ord().comap(P.<K, Option<V>>p2().f(k).<V>o(Option.<V>some_())));
    return tree.split(p(k, Option.<V>none())).map1(getSome).map3(getSome)        
        .map2(Option.<V>join().o(P2.<K, Option<V>>__2().mapOption()));
}

and I'm pretty sure the problem is in extrapolating an Ord for values (which may not be comparable at all) from the Ord provided for the keys using a comap. What the current implementation does is map each value v to (k, some(v)), where k is the split key. Unfortunately, the original Ord only considers the first part of the tuple, which is now the constant k for all values. So this comapping effectively makes all values in the set equal, and thus no value inserts after the first one.

Tony on #functionaljava mentioned that TreeMap might have taken some strong implementation cues from Haskell's Data.Map. Here's the signatures for the splits of that structure:

split :: Ord k => k -> Map k a -> (Map k a, Map k a)
splitLookup :: Ord k => k -> Map k a -> (Map k a, Maybe a, Map k a)

I'm happier with this implementation, because we're not returning back sets of values, but rather submaps, so we don't have to deal with having an Ord for values at all.

If you guys are in agreement of how to resolve this, I can put together a pull request with the fix and necessary tests.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions