-6

Unlike Python, Java doesn't natively support tuples. Therefore, is doesn't provide such a useful possibility as tuple assignment.

How would you implement it? Your solution should:

  1. Be as universal as possible.
  2. Be as readable as possible.
  3. Contain no temporary variables at the place of assignment.
  4. Utility methods are allowed, but only static ones. No Tuple classes should be created or imported. No arrays or collections should be used.

I'll give a simple example. Don't pay much attention to contents of the *Func() methods. They may be inlined or depend on less variables or on other variables additionally.

public class TupleAssignment {
    static String sFunc(String s, int i, double d) {
        return i + s + d;
    }

    static int iFunc(String s, int i, double d) {
        return i + s.length() - (int) d;
    }

    static double dFunc(String s, int i, double d) {
        return (double) i / s.length() + d;
    }

    public static void main(String[] args) {
        String s = "ABCDE";
        int i = 2;
        double d = 0.6;

        String s1 = sFunc(s, i, d);
        int i1 = iFunc(s, i, d);
        double d1 = dFunc(s, i, d);
        s = s1;
        i = i1;
        d = d1;

        System.out.println(s + ", " + i + ", " + d);
    }
}

This produces the right result:

2ABCDE0.6, 7, 1.0

but requires additional variables s1, i1, d1. If you try to get rid of them this way:

s = sFunc(s, i, d);
i = iFunc(s, i, d);
d = dFunc(s, i, d);

you'll get the wrong result:

2ABCDE0.6, 11, 1.8222222222222224

How to get previous result complying with the above four requirements? If you see a nice partial solution, add it as an answer too.

Note that this question is not about making Tuples. You don't need to implement tuple return values. You don't even need to know what a tuple is. It is about multiple-assignment (call this simultaneous assignment or vector-assignment, if you prefer).

John McClane
  • 3,498
  • 3
  • 12
  • 33
  • 1
    I'd probably implement it by importing the `javatuples` library into my project. https://www.javatuples.org/ – The Head Rush Dec 14 '18 at 19:10
  • @TheHeadRush This doesn't make difference from creating them for yourself. Edited the question to clarify that. – John McClane Dec 14 '18 at 19:17
  • 1
    I think i'd argue that not having to create it makes a huge difference in time cost. Only reason i can see to roll your own is as an academic exercise. – The Head Rush Dec 14 '18 at 19:21
  • @TheHeadRush OK, let's assume that you've found a great Tuple class like that one that you've pointed to and are using it. Write a couple of lines to compare the Python tuple assignment and Java variant that uses that Tuple class. You'll see that you need at least to **extract** fields from this class using some `getValue*()` methods and to assign them to your variables - that is less readable than having two lists side by side. That's why I prioritized **readability**. – John McClane Dec 14 '18 at 19:38
  • 1
    Based on the phrasing, it sounds like you copied and pasted a school assignment and are expecting us to do it for you (hence my downvote). Can you [edit] to clarify? – EJoshuaS - Stand with Ukraine Dec 14 '18 at 20:08
  • @EJoshuaS This is not a school assignment. I plan to add my own answer later (If I have time to do it before they closed the question). – John McClane Dec 14 '18 at 20:23
  • There is a discussion [here](https://groups.google.com/forum/m/#!topic/guava-discuss/GF4QyBu0gsI) about why pairs (and by extension tuples) are a bad idea. – Andy Turner Dec 14 '18 at 20:33
  • @AndyTurner Could you write out the most notable (in your opinion) argument against tuples from that discussion here? – John McClane Dec 14 '18 at 22:58
  • Either use c++, or scala. Scala is probably closer to Java, so go with that. – smac89 Dec 15 '18 at 02:06
  • @smac89 Thanks, but I've already made my choice. c++ is too old, Scala is still too young to replace Java. – John McClane Dec 15 '18 at 02:51

1 Answers1

2

I wouldn't. They are a terrible idea. Just make yourself a tiny second class inside the same class as the method that wants to return the value.

public Class ReturnValue{public int age; public String name;}

or if you are paranoid

public Class ReturnValue{
    public final int age; 
    public final String name;
    public ReturnValue(int pAge, String pName){age=pAGe;name=pName;}
}

but if it's REALLY just replacing a tuple, that's a bit verbose

Chances are that once you have created this little class you may find it useful and end up adding methods to it, making the public variables private (or final with a good constructor) and moving it into it's own file--before you know it it's a full-fledged working class that you were missing all along and wouldn't have even KNOWN you were missing if java supplied tuples.

Normally I'd have an issue with mutable public variables, but IF the class is simply being used as a tuple then it's fine, the values will be immediately extracted. If it's not then you have recognized the utility of the class and should refactor it to be a real class.

In your example you are definitely missing a class. I'd suggest:

class Func(String s, int i, double d) {
    final String s;
    final int i;
    final double d;

    public String sFunc() {
        return i + s + d;
    }
    public int iFunc() {
        return i + s.length() - (int) d;
    }

    public double dFunc() {
        return (double) i / s.length() + d;
    }
}

public class TupleAssignment {
    public static void main(String[] args) {
    private func=new Func("ABCDE", 2, 0.6);

    String s = sFunc();
    int i = iFunc();
    double d = dFunc();

    System.out.println(s + ", " + i + ", " + d);
}

The point is that when you want to interact with a group of variables they are likely related and if you put them into a class you will probably end up leaving them there and expanding that class with additional functionality.

If you have a crutch you might not create the new class you need and might try to do everything in one class

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • It can easily be implemented as an immutable class. Just have the set methods return a new object rather than changing the called object. And don't call them set to avoid confusion. – Jonathan Rosenne Dec 14 '18 at 19:17
  • My main goal was class size, one liner no methods. Couldn't figure out how to make that immutable. I have previously done this with a constructor and public final variables which does make it safe but it adds a lot of nonsense code for something you are going to throw away immediately. (And as I said, if you don't throw it away you probably want to add methods to it and make it into a full-fledged class) – Bill K Dec 14 '18 at 19:18
  • In which place of question's code do you propose to insert your `ReturnValue` class? `sFunc`, `iFunc` and `dFunc` are just examples. Consider them as they are inlined (i.e. `s1 = i + s + d;` etc.) – John McClane Dec 14 '18 at 20:11
  • @JohnMcClane Updated answer. If they are inlined, feel free to extract them into a method. PS. I have used tuple assignment in Groovy for fun but it tends to be less readable and causes you not to create the small useful classes that grow into actual code. – Bill K Dec 14 '18 at 21:35
  • What if all you were to do was just to swap two variables (as at the Python link I gave at the beginning of the question)? Is it a good idea to create a class for that? – John McClane Dec 14 '18 at 23:42
  • @JohnMcClane If most of your variables are final (as they should be), that is impossible anyway. – Bill K Dec 15 '18 at 00:49
  • @JohnMcClane I should have mentioned that my comments are all assuming you are doing enterprise code. If you are just coding for yourself or coding scripts, go for it but in that case why are you using java? I use Groovy for all that--syntax practically identical to java but supports things like, oh say tuple assignment (along with a lot of other changes that make it more applicable to scripting than enterprise development). Gotta use the right tool for the right job and all. – Bill K Dec 15 '18 at 01:23