You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Stephen Colebourne <sc...@joda.org> on 2011/03/04 12:41:21 UTC

[lang3] Pair

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?

Stephen

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


Re: [lang3] Pair

Posted by Stefan Bodewig <bo...@apache.org>.
On 2011-03-04, Matt Benson wrote:

> Another interesting concept mentioned in this article is the
> summarized by the statement "Another way of formalizing tuples is as
> nested ordered pairs."  I would argue that this is the only efficient
> way to formally represent an n-tuple using Java generics without
> writing one class per value of n.

To go even further off topic 8-)

.NET 4's classlib has Tuple<T1, T2> up to one with nine generics and the
recommended approach for more than nine is to use a Tuple of appropriate
length as the last type of the nine generics Tuple.

The accessors are Item1 to Item9.

Given that .NET's generics implementation is quite a bit more advanced
than Java's they don't need to implement special cases for primitives.

> Call it a pair, call it an association, but let's call it done.

+1 even if I'm not even a user of [lang].

Stefan

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


Re: [lang3] Pair

Posted by Gary Gregory <ga...@gmail.com>.
On Fri, Mar 4, 2011 at 3:31 PM, Matt Benson <gu...@gmail.com> wrote:

> On Fri, Mar 4, 2011 at 2:29 PM, Matt Benson <gu...@gmail.com> wrote:
> [SNIP]
> > From http://en.wikipedia.org/wiki/Tuple:  "a 2-tuple is called a
> > pair".  Not necessarily authoritative, but amusing nevertheless.
> >
> > Another interesting concept mentioned in this article is the
> > summarized by the statement "Another way of formalizing tuples is as
> > nested ordered pairs."  I would argue that this is the only efficient
> > way to formally represent an n-tuple using Java generics without
> > writing one class per value of n.
>
> Well, perhaps not "efficient," but still the only way to represent an
> arbitrary number of type parameters.
>

In this case, we need a 2-tuple, nothing more. We can more later of course,
a la .NET or not.

Gary


>
> Matt
>
> >
> > Call it a pair, call it an association, but let's call it done.
> >
> > Matt
> >
> >> 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<gu...@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
> >>
> >
>
> ---------------------------------------------------------------------
> 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

Re: [lang3] Pair

Posted by Matt Benson <gu...@gmail.com>.
On Fri, Mar 4, 2011 at 2:29 PM, Matt Benson <gu...@gmail.com> wrote:
[SNIP]
> From http://en.wikipedia.org/wiki/Tuple:  "a 2-tuple is called a
> pair".  Not necessarily authoritative, but amusing nevertheless.
>
> Another interesting concept mentioned in this article is the
> summarized by the statement "Another way of formalizing tuples is as
> nested ordered pairs."  I would argue that this is the only efficient
> way to formally represent an n-tuple using Java generics without
> writing one class per value of n.

Well, perhaps not "efficient," but still the only way to represent an
arbitrary number of type parameters.

Matt

>
> Call it a pair, call it an association, but let's call it done.
>
> Matt
>
>> 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<gu...@gmail.com>  wrote:
>>>>
>>>>  On Fri, Mar 4, 2011 at 5:41 AM, Stephen Colebourne<sc...@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
>>
>

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


Re: [lang3] Pair

Posted by Matt Benson <gu...@gmail.com>.
On Fri, Mar 4, 2011 at 1:45 PM, Gary Gregory <ga...@gmail.com> wrote:
> 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>.
>

>From http://en.wikipedia.org/wiki/Tuple:  "a 2-tuple is called a
pair".  Not necessarily authoritative, but amusing nevertheless.

Another interesting concept mentioned in this article is the
summarized by the statement "Another way of formalizing tuples is as
nested ordered pairs."  I would argue that this is the only efficient
way to formally represent an n-tuple using Java generics without
writing one class per value of n.

Call it a pair, call it an association, but let's call it done.

Matt

> 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<gu...@gmail.com>  wrote:
>>>
>>>  On Fri, Mar 4, 2011 at 5:41 AM, Stephen Colebourne<sc...@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
>

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


Re: [lang3] Pair

Posted by Gary Gregory <ga...@gmail.com>.
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<gu...@gmail.com>  wrote:
>>
>>  On Fri, Mar 4, 2011 at 5:41 AM, Stephen Colebourne<sc...@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

Re: [lang3] Pair

Posted by Adrian Crum <ad...@sandglass-software.com>.
+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<gu...@gmail.com>  wrote:
>
>> On Fri, Mar 4, 2011 at 5:41 AM, Stephen Colebourne<sc...@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


Re: [lang3] Pair

Posted by Gary Gregory <ga...@gmail.com>.
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 <gu...@gmail.com> wrote:

> On Fri, Mar 4, 2011 at 5:41 AM, Stephen Colebourne <sc...@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

Re: [lang3] Pair

Posted by Henri Yandell <fl...@gmail.com>.
+1 for you to go ahead and put something in. We can pull if it feels
that everything else is ready and Pair et al are not there yet.

Hen

On Sat, Mar 5, 2011 at 11:28 AM, Stephen Colebourne
<sc...@joda.org> wrote:
> On 4 March 2011 18:35, Matt Benson <gu...@gmail.com> wrote:
>> 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.
>
> Since the existing Pair class can't be altered after the fact, we need
> to ship without it, or code this up quickly.
>
>> 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) {}
>> }
>
> These class outlines are very similar to what I would propose from
> OpenGamma. I'll need to check on Monday, but with those three classes
> as they are above, I'd probably be happy.
>
>> 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.
>
> Typically, the order is of some significance, as the generics force you to care.
>
>> 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 think that [lang] could probably stop with the three classes above,
> and leave primitive implementations to others.
>
> BTW, Pair is the right class name given how I've seen it discussed in
> various places.
>
> 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


Re: [lang3] Pair

Posted by Stephen Colebourne <sc...@joda.org>.
On 4 March 2011 18:35, Matt Benson <gu...@gmail.com> wrote:
> 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.

Since the existing Pair class can't be altered after the fact, we need
to ship without it, or code this up quickly.

> 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) {}
> }

These class outlines are very similar to what I would propose from
OpenGamma. I'll need to check on Monday, but with those three classes
as they are above, I'd probably be happy.

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

Typically, the order is of some significance, as the generics force you to care.

> 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 think that [lang] could probably stop with the three classes above,
and leave primitive implementations to others.

BTW, Pair is the right class name given how I've seen it discussed in
various places.

Stephen

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


Re: [lang3] Pair

Posted by Matt Benson <gu...@gmail.com>.
On Fri, Mar 4, 2011 at 5:41 AM, Stephen Colebourne <sc...@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


Re: [lang3] Pair

Posted by Matt Benson <gu...@gmail.com>.
On Fri, Mar 4, 2011 at 10:29 AM, Henri Yandell <fl...@gmail.com> wrote:
[SNIP]
> I want to change the release style of Lang - I want to release every
> couple of issues once we get Lang 3.0 out. Or every month. I want
> 3.0.68 to exist :) Missing the 3.0 date shouldn't be an issue at all
> unless it's a backwards compat issue.
>

+1; IMHO we need to strive for this across all components, and having
clear and foolproof release instructions should be a tremendous help
in this case.

Matt

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


Re: [lang3] Pair

Posted by Henri Yandell <fl...@gmail.com>.
On Fri, Mar 4, 2011 at 3:41 AM, Stephen Colebourne <sc...@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 :-)

CCLA up to you and your company. You've signed a CLA so no concerns on my part.

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

Charge along with your ideas, once other topics are refined we can
branch 3.x off to 3.0 and refine that there while Pair continues if
need be.

I want to change the release style of Lang - I want to release every
couple of issues once we get Lang 3.0 out. Or every month. I want
3.0.68 to exist :) Missing the 3.0 date shouldn't be an issue at all
unless it's a backwards compat issue.

Hen

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