On Fri, Mar 4, 2011 at 2:29 PM, Matt Benson <gudnabr...@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<gudnabr...@gmail.com> wrote: >>>> >>>> On Fri, Mar 4, 2011 at 5:41 AM, Stephen Colebourne<scolebou...@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-unsubscr...@commons.apache.org >>>>>> For additional commands, e-mail: dev-h...@commons.apache.org >>>>>> >>>>>> >>>>>> --------------------------------------------------------------------- >>>>> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org >>>>> For additional commands, e-mail: dev-h...@commons.apache.org >>>>> >>>>> >>>>> >>>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org >>> For additional commands, e-mail: dev-h...@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-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org