commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Gary Gregory <garydgreg...@gmail.com>
Subject Re: [lang3] Pair
Date Fri, 04 Mar 2011 19:24:55 GMT
Can we talk about the class name and use cases?

For me a pair evokes similarity: a pair of shoes, a pair of hands, a pair of
coordinates. You get the idea. Having a Pair.of(name, dog) reads like
nonsense to me. A Map.Entry.of(name, dog) I understand, same for an
Association.of(name, dog) (I cannot escape from my Smalltalk heritage.)

In most cases, I deal with key-value "pairs", let's play:

new Pair(name, dog)
new KeyValue(name, dog)
new Association(name, dog)
new MapEntry(name, dog)

If we want to accommodate "real" pairs like a Point2D(x,y), which we should,
then the Pair name makes perfect sense IF it is a Pair<T> where the x and y
are both Ts.

There are two uses cases: pairs and key-value associations.

It would then be interesting for the Pair<T> and KeyValue(K,V) interfaces to
share a common implementing base class, a something that holds two objects
(a TwoTuple, yikes?)

Let's play (these are immutable for brevity):

public interface TwoTuple<E1,E2> {
    E1 getFirst();
    E2 getSecond();
}

public interface Pair<T> extends TwoTuple<T, T> {
}

public interface Association<K, V> extends TwoTuple<K, V> {
    K getKey();
    V getValue();
}

Thoughts?

Gary


On Fri, Mar 4, 2011 at 1:35 PM, Matt Benson <gudnabrsam@gmail.com> wrote:

> On Fri, Mar 4, 2011 at 5:41 AM, Stephen Colebourne <scolebourne@joda.org>
> wrote:
> > I now have authoristion from OpenGamma to discuss adding a Pair class
> > to [lang] based on our internal classes. If necessary a CCLA can be
> > signed, although since we are not necessarily importing the OpenGamma
> > classes as is and I'd be writing code in [lang3] with my Apache hat
> > on, the CCLA might not be needed. I can also code it in work time :-)
> >
> > The main goal would be either an abstract class or an interface for
> > Pair. We chose an abstract class so that it could have factory
> > methods:
> >
> >  Pair<String, Number> p = Pair.of("Foo", 6);
> >
> > It also allowed more control over the immutability of Pair (although
> > because its abstract and holds references to any object, immutability
> > cannot be guaranteed).
> >
> > We then have other concrete classes:
> > - ObjectsPair - two generified objects
> > - DoublePair - two double
> > - IntDoublePair - int and double
> > - LongDoublePair - long and double
> > - IntObjectPair - int and generified object
> > - LongObjectPair - long and generified object
> >
> > Clearly there are many more possible combinations, but some make less
> > sense than others. (Booleans don't waste space, as they are a
> > singleton reference, short/float are rarely used)
> >
> > Beyond this, there are some standard comparators.
> >
> > Design wise, we implement Map.Entry (makes sense). The primitive
> > classes implement primitive map entry interfaces from another library,
> > but that wouldn't make sense here. They are comparable and
> > serializable (again, one reason for an abstract class).
> >
> > We name our elements "first" and "second".
> >
> > The elements are available by methods (for generics) or as public
> > final variables from the concrete classes (not the abstract one). The
> > methods are getFirst(), getSecond() plus getKey() and getValue() for
> > Map compatibility.
> >
> > The pairs are implemented as immutable. I saw someone mention the
> > possibility of a mutable pair, so perhaps we consider that.
> >
> > I don't want this to be a long process of design or implementation! If
> > there isn't rapid consensus, I'd suggest either shipping [lang3] with
> > or without the existing class.
> >
> > Opinions?
>
> I agree that it would be nice to do whatever we're going to do
> quickly, and ship with *something*.  On the other hand, I don't want
> to ship the existing class without consensus on design, only to give
> ourselves (and users) headaches trying to replace it in a subsequent
> release.
>
> I also had the thought that the abstract class would be necessary for
> the factory methods.  It doesn't seem important, but I'd really like
> to be able to say Pair.of(X, Y).  Semantically it'd also be nice to be
> able to use fields on the immutable variety of Pair (it's perhaps
> debatable in light of JIT whether the final field access yields better
> performance, so I won't address it--but it *looks* faster :P ), while
> still requiring the client to know as little as possible about the RT
> type of the Pair.  Is it possible to accomplish all these things?
>
> abstract class Pair<L, R> implements Map.Entry<L, R> {
>  abstract L getLeft();
>  abstract R getRight();
>  final L getKey() { return getLeft(); }
>  final R getValue() { return getRight(); }
>  static <L, R> ImmutablePair<L, R> of(L, R) {}
> }
>
> class ImmutablePair<L, R> extends Pair<L, R> {
>  final L left;
>  final R right;
>  ImmutablePair(L left, R right) { this.left = left; this.right = right; }
>  L getLeft() { return left; }
>  R getRight() { return right; }
>  static <L, R> ImmutablePair<L, R> of(L, R) {}
> }
>
> class MutablePair<L, R> extends Pair<L, R> {
>  private L left;
>  private R right;
>
>  MutablePair(L left, R right) { setLeft(left); setRight(right); }
>  L getLeft() { return left; }
>  setLeft(L left) { this.left = left; }
>  R getRight() { return right; }
>  setRight(R right) { this.right = right; }
>  static <L, R> MutablePair<L, R> of(L, R) {}
> }
>
> In the examples above I continue to use the left/right idiom for
> reasons of inertia; in the end, I don't *really* care.  It seems
> examples abound of the various proposed paired names in other
> programming contexts, so this becomes a simple matter of taste and/or
> majority rules.  Personally I prefer left/right as there is less
> connotation of priority given either member of the pair as (IMO) in
> the case of first/second.
>
> If we want to extend ImmutablePair for the wrapper types (it wouldn't
> seem to make sense to provide access to the primitive equivalent
> values in the MutablePair variety), where does it end?  If we provide
> any such pair types, IMO we should use some predictable rule to
> define, for a given wrapper type, what combinations are available,
> e.g.:
>
> * X Double
> * X Boolean
> * X Object
> * X self
> * X * ?
>
> I'm sure I don't have to tell any of my fellow Commons committers that
> our components may well have to provide more implementations, or none
> at all, compared to equivalent proprietary code, for reasons of
> perceived "completeness."  If anything this is even more so in the
> case of [lang] than perhaps some other Commons components.
>
> Matt
>
> >
> > Stephen
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> > For additional commands, e-mail: dev-help@commons.apache.org
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
>
>


-- 
Thank you,
Gary

http://garygregory.wordpress.com/
http://garygregory.com/
http://people.apache.org/~ggregory/
http://twitter.com/GaryGregory

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message