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:45:49 GMT
On Fri, Mar 4, 2011 at 2:36 PM, Adrian Crum <
adrian.crum@sandglass-software.com> wrote:

> +1 on the Association interface.
>
> The Tuple interface looks like a Collection, even more so when it expands
> to more than two elements.
>

Not quite, because you can only type a collection as Collection<E>, not
Collection<E1, E2>.

Gary


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


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