Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Pair class and Itera*s.pairUp() #203

Closed
gissuebot opened this issue Oct 31, 2014 · 25 comments
Closed

Add Pair class and Itera*s.pairUp() #203

gissuebot opened this issue Oct 31, 2014 · 25 comments

Comments

@gissuebot
Copy link

Original issue created by rafaeldff on 2009-07-13 at 02:58 AM


A common operation in functional programming languages is zip, which takes
two lists and returns a list of pairs of elements, whose elements are the
elements of the input lists at corresponding position. One problem is that
there are no Pairs (nor any other tuples) in the JDK, but maybe Map.Entry
could be repurposed for this:

public static <A, B> Iterator<Entry<A, B>> zip(final Iterator<A> first,
final Iterator<B> second) {
        return new AbstractIterator<Entry<A,B>>(){
            @Override
            protected Entry<A, B> computeNext() {
                if (!first.hasNext() || !second.hasNext()) {
                    return endOfData();
                }

            return Maps.immutableEntry(first.next(), second.next());
        }
    };
}
@gissuebot
Copy link
Author

Original comment posted by creswick on 2009-07-13 at 04:59 PM


I like the idea of zip functions, but I do not think that repurposing Map.Entry is a
good idea for something as simple as a tuple type. (It also makes sense to have
tuple types of multiple cardinalities, and those should share a naming convention,
which won't be possible with Map.Entry.)

In practice, I find Iterable<T> zipWith(Function2&lt;R,S,T>, Iterable&lt;R>, Iterable&lt;S>) to be more useful, but that would require a set of Function objects
with higher arity (eg: Function2<R,S,T>). In the zip case, we need tuples, and in
the zipWith case we need new Function objects, but they can accomplish essentially
the same thing either way. My preference is to add increased Arity functions, since
tuples are rarely the final objective (in my experience), and functions of 2+
parameters can be useful in other contexts as well (fold/reduce for example)

@gissuebot
Copy link
Author

Original comment posted by rafaeldff on 2009-07-14 at 04:28 AM


I agree that having tuple classes would be an improvement over the version with
Map.Entry.

The proposal to add a method that combines a map with a zip is also fine by me, but
not in detriment of a simple zip. The issue is not so much that there are cases where
tuples aren't the final objective, but that Java's inner class syntactic verbosity
makes working with Functions burdensome.

@gissuebot
Copy link
Author

Original comment posted by jvdneste on 2009-07-14 at 10:46 AM


There are already quite a few existing issues regarding functional programming
facilities. Have a look around. The basic requirement to move forward is a tuple
library (or at least a Pair object). The impression I got is that the google
collections maintainers are undecided on where to go with regard to functional
programming. The verbosity is a big problem. Since the maintainers seem to be in
(relatively close) contact with Joshua Bloch, I also suspect they know things about
where the java language/platform is headed that we don't know.

@gissuebot
Copy link
Author

Original comment posted by jared.l.levy on 2009-07-16 at 11:07 PM


Internally, Google has a Pair class, along with Iterators and Iterables methods that
are similar to zip. We may release them at some point, but not in version 1 of Google
Collections.

@gissuebot
Copy link
Author

Original comment posted by kevinb9n on 2009-08-12 at 05:59 PM


No promises that we will get to this, but the request makes sense.


Status: Accepted
Labels: post-1.0

@gissuebot
Copy link
Author

Original comment posted by earwin on 2009-08-12 at 11:49 PM


+1 for Map.Entry compatible Pair. That's a class I've seen reinvented in every
project with enough complexity.

@gissuebot
Copy link
Author

Original comment posted by kevinb9n on 2009-09-17 at 05:45 PM


(No comment entered for this change.)


Labels: -post-1.0, Milestone-Post1.0

@gissuebot
Copy link
Author

Original comment posted by kevinb9n on 2009-09-17 at 05:57 PM


(No comment entered for this change.)


Labels: Type-Enhancement

@gissuebot
Copy link
Author

Original comment posted by kevinb@google.com on 2010-07-30 at 03:53 AM


(No comment entered for this change.)


Labels: -Milestone-Post1.0

@gissuebot
Copy link
Author

Original comment posted by morten.hattesen on 2011-03-19 at 05:17 PM


I'd like to see the Pair class make it into Guava soon.
It seems to fit the purpose of Guava - commonly used (and reimplemented).

@gissuebot
Copy link
Author

Original comment posted by amertum on 2011-03-22 at 08:50 AM


I don't really like the idea of tuple class. At first it looks great but when you have a lot of Pair, Triple... and so on, you have lost the meaning of the tuple name.

I saw things like a value and a currency goes into a Pair or worst a Map.Entry while it is an Amount. The cost to write an Amount class (or whatever that fits better) is really really better IMHO.

@gissuebot
Copy link
Author

Original comment posted by eric.jain on 2011-03-22 at 04:56 PM


If Java had something like Scala's case classes that generate the equals/hashCode/toString methods and can be defined in one line, I'd agree that a Pair class doesn't add much value.

@gissuebot
Copy link
Author

Original comment posted by kandpwelker on 2011-07-13 at 05:07 AM


I have been playing with the design of Tuples, and what has been convenient is to have a Tuples class with the different predefined arities implemented as static classes within the Tuples class so that you can statically import the whole thing to get all of your arity types and static factory methods at the same time.

For notational brevity, the types could be implemented with names such as "_1" (for arity 1), "_2" (for arity 2, etc.) That kind of naming may seem like anathema to some, but without the static import it would read more explicitly as Tuples._1, Tuples._2, etc.

And the many overloaded static factory methods would share the same name which would serve to look almost like an operator: "_"

So to create a new pair or triplet with static imports, it would simply look like:
_2<T1, T2> myPair = _(obj1, obj2);
_3<T1, T2, T3> myTriplet = _(obj1, obj2, obj3);

@gissuebot
Copy link
Author

gissuebot commented Oct 31, 2014

Original comment posted by j...@nwsnet.de on 2011-07-13 at 10:45 AM


I just like to share my two implementations of "zip": one cutting off the longer input iterable, the other one padding the shorter input iterable.

They are named after Scala's, from which I also learned about the idea of providing pad values instead of using null as a default.

Regarding a pair/tuple class, I currently have no further ideas except for accepting a function argument that would be called for every pair to be created, allowing instanciation of a custom pair class for the current domain and use case. That is a lot of overhead (at least in reading and writing the code), though.

@gissuebot
Copy link
Author

Original comment posted by kevinb@google.com on 2011-07-13 at 06:18 PM


(No comment entered for this change.)


Status: Triaged

@gissuebot
Copy link
Author

Original comment posted by fry@google.com on 2011-12-10 at 03:39 PM


(No comment entered for this change.)


Labels: Package-Base

@gissuebot
Copy link
Author

Original comment posted by kevinb@google.com on 2012-02-16 at 06:47 PM


We've discussed this extensively and we have decided that we will not be releasing a Pair class in Guava. Sorry!


Status: WorkingAsIntended

@gissuebot
Copy link
Author

Original comment posted by bolinfest on 2012-11-12 at 05:51 PM


FYI, the Idea Graveyard (http://code.google.com/p/guava-libraries/wiki/IdeaGraveyard) has a more detailed explanation of why there is no Pair class in the "Tuples for n >= 2" section.

@gissuebot
Copy link
Author

Original comment posted by morten.hattesen on 2012-11-12 at 05:59 PM


I wonder what the rationale for rejecting a tuple with n=2 (i.e. a Pair) is, though.

Guess we'll never know.

@gissuebot
Copy link
Author

Original comment posted by lowasser@google.com on 2012-11-12 at 06:16 PM


Eh? The rationale's right there, in the same place.

@gissuebot
Copy link
Author

Original comment posted by morten.hattesen on 2012-11-12 at 06:34 PM


OK, my bad.

I still wonder, though, what makes so may projects roll their own Pair
class when "we found that all of its users could be better served in other
ways", which I guess is the rationale for not doing it.

I'll leave this issue to the peace of the Ideas Graveyard.

@gissuebot
Copy link
Author

Original comment posted by alex.panchenko on 2012-11-13 at 02:34 AM


I agree, that it could be easily abused by using it instead of Point or whatever classes. However, there is nothing bad when using it locally as Map key for example. That's the motivation of having it in many projects, as quite often you are getting tired of defining *Key classes multiple times.

@gissuebot
Copy link
Author

Original comment posted by jbellis on 2012-11-13 at 02:38 AM


Also, method return values. Sometimes the values you want to return are unrelated except by the fact that they are computed together.

@gissuebot
Copy link
Author

Original comment posted by wasserman.louis on 2012-11-13 at 04:24 AM


We're quite firm in our opinion, but to give a bit more detail --

a) If you're using a pair as a Map key, you'd probably be better off using a Table, not a Map.
b) If you're returning two values from a method, usually what we've found in code we've refactored is that either they are related, or the code can be structured more effectively to avoid that issue in the first place.

@gissuebot
Copy link
Author

Original comment posted by Maaartinus on 2012-11-13 at 05:40 AM


I sort of agree with your reasons against Pair, but to give some (sort of real-world) counter examples:

a) I'm caching a binary function and there's nothing like TableCache. Even if there was such a thing, it would probably consume more time and space.
b) From a collection of Rule implements Function<State, State> one rule gets chosen and applied to the current state. Both the new state and the chosen rule get returned. There are ways to avoid it but they all feel like a workaround.

Anyway, using getFirst/Second is ugly, but not as ugly as writing a one-shot class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant