commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Adrian Crum <adrian.c...@sandglass-software.com>
Subject Re: [lang3] Pair
Date Fri, 04 Mar 2011 19:36:26 GMT
+1 on the Association interface.

The Tuple interface looks like a Collection, even more so when it 
expands to more than two elements.

-Adrian

On 3/4/2011 11:24 AM, Gary Gregory wrote:
> 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
>>
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Mime
View raw message