On Fri, Mar 4, 2011 at 2:36 PM, Adrian Crum < adrian.c...@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<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