This question [1] got me re-thinking about something that always bothered me:
Does Java need tuples?
Do you feel the lack of them in your day-to-day work? Do you think tuples would simplify otherwise complex data structures you find yourself implementing?
I don't think that Java needs tuples, but they would certainly be nice to have in certain situations.
It's not much work to write a generic Pair<A, B> class, or a Triple<A, B, C> class, which gets you most of the benefits of tuples, but the approach does not generalise to n-tuples.
I think it does, but only in the context of supporting multiple return values. I'd like to see a method like that pike, python, perl etc copied for supporting creating a form of hidden data-structure as a return-type and linking an assignment to the invocation of said return type...as follows:
a, b = method();
And with the following, strangely obvious, return syntax:
return a, b;
And similarly it should be paired with the ability to create an array from said values, assuming there is no type mismatch. This type mismatch could easily be caught and enforced at compile time with a runtime classcastexception for when type-safety is circumvented, much like it would be today in other contexts.
Object[] results = method();
Similarly, since coersion into an array is as straight-forward as having a tuple who's all values are only a single type, it makes rather logical sense that the converse would be possible as well:
a, b = results;
Of course, this would be type-safe. Under the covers, the tuple could just be an array of Object[] much how generics are largely compile-time enforced now, and the syntax of method invocation with multiple return values could simple be translated into corresponding op-codes to take an array of object back and copy the values into the identifiers specified as capturing the result. Type-safety could be a compile-time-only enforcement, and this would avoid adding a real new language concept to the JVM and remain that multiple return values are simply syntactic sugar, and backward/forward compatibility could be upheld since the runtime byte-code would be tuple-unaware. Everything would just look like a really annoying array of object, to all those Java 6 programmers.
I think it definitely does. But tuples are just one of many language features that Java lacks, including closures and basic type inference. It's interesting to see how Scala will do in the future, as this is a JVM-language that implements a lot of the sexy language features that Java lacks.
EDIT: Of course, for tuples to be effective in Java as a native language feature, some sort of pattern matching is also required.
Here is another argument for tuples: Hashable tuples can be used as keys for hash maps. I don't know how many times I created hash map keys by joining string representations of two or more objects. If I had tuples, I could write
Tuple key = new Tuple(keyPart1, keyPart2, ..., keyPartN);
hashMap.put(key, value);
and Java would compute the hash of the key efficiently for me.
That's why I need tuples: To combine hashes of objects efficiently.
Does java need to actually be python instead?
Yes it does, big time.
I've been in the same situation often enough, and I admit that in some cases I have initially done the ugly thing of using a pair or a trip. However, I generally strive to refactor these into a real object.
I don't think tuples would add much that you can't achieve with existing mechanisms (especially now that we have generics).
If Java supported Lambdas, then that would be a different thing... :)
Multiple (statically-typed) return values would be useful in some circumstances (although my guess most uses would be abuses). However, a generalised tuple would, I think, be counter to the feel of Java (and would be used almost exclusively for abuse).
I might be on the wrong track here, but isn't Map.Entry [1] a tuple?
Creating a single Entry is fairly ugly, though:
public Map.Entry<String, String> tuple(String key, String value) {
Map<String, String> map = new HashMap<String, String>();
map.put(key, value);
return map.entrySet().iterator().next();
}
[1] http://java.sun.com/j2se/1.5.0/docs/api/java/util/Map.Entry.htmlGood question. No.
I regularly write in Java and Python, and this is exactly the sort of thing I miss when writing Java. However, what you have to remember is those two languages represent two vastly different programming paradigms. Sequences are first-class in python, and they're just another object in Java. Language-level tuples wouldn't fit in with this.
I like Python for what it is, and I like Java for what it is. While I miss features from one while programming in the other, I wouldn't want them to try to emulate each other.
Isn't a data-only class with public fields effectively just a tuple?
Very simply not necessary for an OO language--in fact, detracts from design.
If you have a method that returns two values, either they should be closely related or your method is doing more work than it should.
If they are closely related, they should be parts of an object (like a tuple). But if you are going to do that, why not create a first-class object that can have methods?
If you had tuples, you'd have to have external code to manipulate those tuples. You also wouldn't have any place to put range checking or other validations.
I've often started with a temporary class (structure) with two public variables and before the day was out had a full-fledged class with private members and methods that I missed in my original design.
I've never just left it at a pair of variables, A class seems to always be required--it just tends to work out that way.
If Java had tuples, I may not have been driven to find these design flaws and my code would be worse in every single case.
(Counterexamples welcome)
Yes it does! I am convinced that Java needs tuples and if it does not have it, we can define them for ourselves.
If a problem is functional, you need to program in a functional style. Object oriented style makes things unnecessarily complicated. If a function returns more than one value or structure, you need a tuple. Tuples should be immutable (as in other functional languages) to provide safe programming.
Here is a simple example of a 2-dimensional tuple class:
// pair
public class Tuple2 { public final A item1; public final B item2;
// Constructor from components
public Tuple2(A item1Init, B item2Init)
{
item1 = item1Init;
item2 = item2Init;
}
// Constructor from another Tuple2 with the same types:
public Tuple2(Tuple2 <A, B> anotherTuple2)
{
item1 = anotherTuple2.item1;
item2 = anotherTuple2.item2;
}
// No getters/setters are needed/possible because the components are public/final.
}
You can implement most functionality of tuples with an object (nested class), but that is a bit cumbersome for one-shot usage.
A frequent reason for tuples is needing to return multiple values from a given method call. Here again, a specialized class can substitute.
Also note that you can use an array object from within a method and set its value and use that as a "return many value" holder.
What is the benefit of having tuples without introducing pattern matching on invocation?
Therefore, the question become: «Does Java need tuples and pattern-matching on invocations?»
And subsequently, is it even possible for java to support pattern matching?
Anyone who has used JPA and Object arrays to return multiple items for a JPQL query will tell you Java needs an equivalent of the C# var type.
No, it doesn’t. In my class library here at work I do have a class Pair
but I don’t use it very often and only for internal purposes, i.e. it’s never exposed in a public interface.
What I really miss is some type of list that's not mind-numbingly annoying to work with. If I could declare and use an ArrayList of different types of objects without a metric ass-ton of casting I'd be much happier.
I don't think tuples (in the Python, same-as-lists-but-immutable sense) are really critical though.
Person p = new Person("Steve", System.currentTimeMillis(), 722); System.out.println(p.getName(), p.getLastLogin(), p.getKarma() * 10);
- I don’t see no casts here! :) - Bombe
Well, I found this question by Googling "tuples Java" because I needed them. I like the tuple-less solution I coded up far less than what I could have done had they been present.
I'd rather see Case Classes (from Scala) in Java than tuples. Case class is something like
public class MyClass {
private Integer intField;
private String stringField;
private Date dateField;
public MyClass(Integer intField, String stringField, Date dateField) {
this.intField = intField;
this.stringField = stringField;
this.dateField = dateField;
}
public Date getDateField() {
return dateField;
}
public void setDateField(Date dateField) {
this.dateField = dateField;
}
public Integer getIntField() {
return intField;
}
public void setIntField(Integer intField) {
this.intField = intField;
}
public String getStringField() {
return stringField;
}
public void setStringField(String stringField) {
this.stringField = stringField;
}
}
but you'd write it like this
public case class Myclass(Integer intField, String stringField, Date dateField);
Additionally in Scala pattern matching is done on case classes : http://www.scala-lang.org/node/107
Here is another tuple, pair approach with generics:
public class TuplePair<X, Y, Z> {
private final X first;
private final Y second;
private final Z third;
public TuplePair(X f, Y s, Z z) {
first = f;
second = s;
third = z;
}
...
...
}
Of course you need couples and touples.
How else are you going to represent vertices in 2D and 3D without using per coordinate arrays (2 or 3 parallel arrays - very, very ugly and unsafe) or...
rewriting yourself what should already have been there for you and actually was...
until they deprecated it.
I always just use things like this. Existing, java.util, tested, reusable, just nice.
Map.Entry<String, Boolean> tuple = new AbstractMap.SimpleEntry<String, Boolean>("test",false);
And things also work more complex like: Map.Entry<List<String>, Boolean>
or whatever...
To my standpoint, no, Java does not need tuples. Wait, let me refine it. It would be a BAD idea to implement tuples in Java.
Why? Because of Java way of thinking. Nearly everything in Java is there to prevent runtime errors: statically strong typing, explicit variable declaration, single inheritance, generics, exceptions and so on.
This is the strongest point of Java (with its huge library), and that's why java gains so much popularity in the industry world.
Tuples means implicitly adding dynamic typing and inference, which is completely at the oposite of Java's philosophy.
Not that tuples are bad, I use them happily in other languages, they're just inappropriate for Java.
EDIT: To explain my point about dynamic typing, as said in the comment, I was thinking about an unknown set of return elements.
Anyway, how would we grab the tuple? Using a
val1, val2 = obj.method()
could be fine, but what if you want to use the result as a parameter of another method?