Linked by Bjorn Raupach on Thu 17th Jul 2008 06:01 UTC
Java Today was one of those days when I wished Java would support multiple return values. I had to develop a rather CPU-intensive algorithm which would compute a solution for a knotty constraint problem. Having a solution alone is sometimes not enough and you also need to add some parameters which measure the quality of the computed outcome. Most of these accompanying parameters can or have to be computed within the algorithm itself, but Java allows you to return only one value either an object or a primitive type. People working with Lisp, MATLAB or Perl, just to mention a few, don't have a problem like this at all. Functions supporting multiple return values is already implemented at the language level and frameworks make heavy use of this. But as a Java programmer you are pretty much stuck here and need to consider some other means to come out of this situation. In the following I would like to give some hints on that topic. Hopefully they are of help for anyone having the same problem every now and then.
Order by: Score:
tuples
by averycfay on Thu 17th Jul 2008 17:02 UTC
averycfay
Member since:
2005-08-29

This approach is usually generalized into tuples, which are useful in a number of situations. Examples would be:

for java: http://javatuple.com/
for c++: http://www.boost.org/doc/libs/1_35_0/libs/tuple/doc/tuple_users_gui...

Reply Score: 3

RE: tuples
by FunkyELF on Thu 17th Jul 2008 17:50 UTC in reply to "tuples"
FunkyELF Member since:
2006-07-26

That java link was nice...thanks. Once you start using tuples in other languages like Python you want to use them in everything. I looked at the code hoping it wouldn't be a big mess and it seems pretty clean. Its not a hard concept.

I didn't see a mention of a license in the download though. The site does say

You can compile the source into a jar, or make it part of your project directly.
... so it might be public domain?

EDIT: Just saw it on the bottom.... Creative Commons Attribution 3.0 United States License.

Edited 2008-07-17 17:53 UTC

Reply Score: 2

Obvious...
by Flipper on Thu 17th Jul 2008 17:02 UTC
Flipper
Member since:
2008-07-17

Return object array, object, char separated values? How hard could it be?

Reply Score: 14

Never programmed in Java before...
by FishB8 on Thu 17th Jul 2008 17:05 UTC
FishB8
Member since:
2006-01-16

but couldn't you just return an array of pointers to the multiple data values you want to return?

Reply Score: 3

averycfay Member since:
2005-08-29

but couldn't you just return an array of pointers to the multiple data values you want to return?


1.) Java doesn't have pointers.
2.) There's no type safety in that approach (meaning it's not a good idea for C++ too)

Reply Score: 3

Vanders Member since:
2005-07-06

With C++ you'd just pass multiple values by reference, rather than muck about trying to "return" multiple values.

Reply Score: 2

FunkyELF Member since:
2006-07-26

With C++ you'd just pass multiple values by reference, rather than muck about trying to "return" multiple values.


Then there is no "contract" in the function prototype. It is nice to know by looking at the arguments what can be changed and what can't be changed. You wind up looking at the code to see what is really going on, or actually reading the documentation which nobody wants to do.

Pointers are an ugly hack. The output variable is an input to the function?

Reply Score: 3

ValiSystem Member since:
2006-02-28

C++ allows you to declare constant references and pointers, just for this purpose.

Reply Score: 2

FunkyELF Member since:
2006-07-26

Cool... a hack around a hack ;-)

Reply Score: 2

Vanders Member since:
2005-07-06

Er, not really. const is a standard feature in C++ for declaring, well, constants. Same as it is in C, and it's been that way forever. It's hardly a hack: certainly no more than inventing silly ways to return multiple values from a function.

Also, who said anything about pointers here? C++ supports proper bona fide pass by reference.

Reply Score: 4

renox Member since:
2005-07-06

Er, not really. const is a standard feature in C++ for declaring, well, constants.

Except that const are not always constants in C++.


It's hardly a hack: certainly no more than inventing silly ways to return multiple values from a function.

I find much more readable to have the input variable on one part of the function and the output variables on another part, of course readability isn't C++ strong point.

Reply Score: 2

tristan Member since:
2006-02-01

"but couldn't you just return an array of pointers to the multiple data values you want to return?


1.) Java doesn't have pointers.
2.) There's no type safety in that approach (meaning it's not a good idea for C++ too)
"

My first thought in C++ would be to have a templated ReturnTriple struct along the lines of:

template<class A, class B, class C>
struct ReturnTriple
{
A first;
B second;
C third;
};

which is cheap, type-safe and reusable.

EDIT: Or, as another poster pointed out, just pass parameters by reference. Is this not possible in Java?

Edited 2008-07-17 17:37 UTC

Reply Score: 2

saucerful Member since:
2008-06-12

Java doesn't have data structs so it would have to be a class but the same concept works.

In fact it makes sense... if you're returning multiple values, they have a relationship. Chances are that that relationship will be studied elsewhere in the code. For instance other methods will take as input both of those pieces of data. Or there will be methods that specifically massage that data. What better place to put them than in this return value class? So in the end such a class almost always pays off by making code easier to read and more organized.

Edited 2008-07-17 18:31 UTC

Reply Score: 2

FunkyELF Member since:
2006-07-26

My first thought in C++ would be to have a templated ReturnTriple struct along the lines of:

template
struct ReturnTriple
{
A first;
B second;
C third;
};

which is cheap, type-safe and reusable.

The first poster on here gave a nice link for javatuple which does something very similar. I just looked and it seems real nice. it has classes for Single, Pair, Triple etc. up to Decuple.
I'm not sure if your C++ example retains type safety but this javatuple package does.


EDIT: Or, as another poster pointed out, just pass parameters by reference. Is this not possible in Java?


Java has Objects and primitives (because back in the day people were bitching about performance). Primitives are pass by value, Objects are passed as a reference. This means that if you pass a Vector to a method, because it is an Object, if you add or remove from that Vector in the method the changes will be visible after the method is called. However, even though Integer is a class, there are no methods to change the value of one. So, a method that needs to return two integers could return a List<Integer> or an Integer[], but things get ugly when you need to return an Integer and a String.

Reply Score: 2

msundman Member since:
2005-07-06

Java doesn't have pointers.

Sure java has pointers. You just can't manipulate them.
E.g.:
Object a=new Object(), b=a;
Here a and b are pointers to the same object.

Reply Score: 7

tristan Member since:
2006-02-01

"Java doesn't have pointers.

Sure java has pointers. You just can't manipulate them.
E.g.:
Object a=new Object(), b=a;
Here a and b are pointers to the same object.
"

To a C++ programmer, a and b look a lot more like references than pointers...

Reply Score: 1

ebasconp Member since:
2006-05-09

"[q]Java doesn't have pointers.

Sure java has pointers. You just can't manipulate them.
E.g.:
Object a=new Object(), b=a;
Here a and b are pointers to the same object.
"

To a C++ programmer, a and b look a lot more like references than pointers... [/q]


No, they are not references, they are pointers. The code above is identical to:

Object* a = new Object(), *b = a;

a and b are pointers to the same object.

References in C++ are stuff defined as:

const Object& a = Object::GetSingleton();

a is a const reference to an instance of a class.

Reply Score: 3

IvoLimmen Member since:
2005-07-06

1.) Java doesn't have pointers.

Java works with references and a reference is a typed pointer. So if you use Object you kind of are using pointers...
2.) There's no type safety in that approach (meaning it's not a good idea for C++ too)

Exactly: that's why Java made them type-safe.

Reply Score: 2

ebasconp Member since:
2006-05-09

1.) Java doesn't have pointers.


Where do you get that assert from???

Everything in Java but the primitive data types are referred via pointers (ok, let's call them "references", but in Java they are the same).

When you declare

MyObject obj = new MyObject();

you are creating an instance of class MyObject and you are assigning a pointer to that instance.

The only difference here is that you cannot do pointer arithmetic (as in C).

Reply Score: 4

Ralf. Member since:
2005-08-13

1.) Java doesn't have pointers.


If Java does not have pointers, why is there a "NullpointerException"? ;-)

Reply Score: 3

Good...I have a comment ready...
by FunkyELF on Thu 17th Jul 2008 17:37 UTC
FunkyELF
Member since:
2006-07-26

I've commented on this before ;-)
http://www.osnews.com/thread?318611

Reply Score: 2

v.alexeev Member since:
2008-02-05

Reading Your last argument in the linked post - not convinced.

As it is stated in the next thread, returning multiply results from function absolute most of the time means bad design.

Applied to the example you gave.
You should spend some time and understand what are these tables used for and for how long. If these hashtables are used often I see no reason why shouldn't you use a wrapper. This wrapper may have some of the fetch and common processing logic loaded into to break data and computation apart. If they are short lived - why do you need a separate getter for them anyway?

Edited 2008-07-17 18:32 UTC

Reply Score: 1

FunkyELF Member since:
2006-07-26

If you don't see a reason why I should use a wrapper object, then why don't you see a reason for multiple return values?
It is doing the exact same thing logically.

It isn't often that I need to return multiple things. Hardly ever. I just mentioned one case where it made sense.

If I wanted to be "object oriented" using getters I could call one method compute() like so...
public void compute(){
  SomeClass a = someExpensiveDBOperation();
  // h1 and h2 are class members
  h1 = new HashTable<String, List<String>>
  h2 = new HashTable<String, List<String>>
  while(a.hasMoreCrap()){
    Row r = a.next();
    List<String> list = new ArrayList<String>();
    list.add(r.getString(1));
    list.add(r.getString(2));
    list.add(r.getString(3));
    list.add(r.getString(4));
    h1.put(r.getString(1), list);
    h2.put(r.getString(2), list);
  }
}

Then, when I want h1 or h2, I'd have to call a method like...
public HashTable<String, List<String>> getH1(){
  HashTable<String, List<String>> ret = h1;
  // so we're not hanging onto it forever...
  h1 = null;
  return ret;
}

What an absolute pain in the ass.

Edited 2008-07-17 19:06 UTC

Reply Score: 3

IvoLimmen Member since:
2005-07-06

I don't see your problem, then again I don't know what you are trying to achieve in your program.
I never had the urge to use a multi-value return and I also came from a C++ environment, I never used it because good OO design never needed it.
Sorry to point this out but the fact that you nullify the class field 'h1' before returning the (reference) copy, tells me that you either do not fully understood how Java works or you need some serious OO design classes.

Reply Score: 1

danieldk Member since:
2005-11-18

Sorry to point this out but the fact that you nullify the class field 'h1' before returning the (reference) copy, tells me that you either do not fully understood how Java works or you need some serious OO design classes.


People should also stop using returning implementation types rather than interfaces ;) (in this case HashTable).

Edited 2008-07-17 20:20 UTC

Reply Score: 3

FunkyELF Member since:
2006-07-26

People should also stop using returning implementation types rather than interfaces ;) (in this case HashTable).


I know it should have returned Map. I just wrote that quick and dirty...there are probably syntax errors too.

Reply Score: 2

IvoLimmen Member since:
2005-07-06

People should also stop using returning implementation types rather than interfaces ;) (in this case HashTable).

You are sooooo right!

Reply Score: 1

FunkyELF Member since:
2006-07-26

I don't see your problem, then again I don't know what you are trying to achieve in your program.
I never had the urge to use a multi-value return and I also came from a C++ environment, I never used it because good OO design never needed it.
Sorry to point this out but the fact that you nullify the class field 'h1' before returning the (reference) copy, tells me that you either do not fully understood how Java works or you need some serious OO design classes.


It is client server. The client needs the HashTables two different ways. Nullifying it on the server and returning it to the client makes it a candidate for garbage collection on the server where I didn't want it hanging around.

All I'm saying is that there are places where multiple return values would be nice. It is basically returning a tuple but without creating meaningless wrapper classes.

Reply Score: 2

IvoLimmen Member since:
2005-07-06


It is client server. The client needs the HashTables two different ways. Nullifying it on the server and returning it to the client makes it a candidate for garbage collection on the server where I didn't want it hanging around.
All I'm saying is that there are places where multiple return values would be nice. It is basically returning a tuple but without creating meaningless wrapper classes.

This this does not explain this piece of code. When there are no references to a object then the garbage collector will reap it. Nullifying an object only helps if you have the only reference to an object but you just passed a copy as return value, hence: there is still a reference.
As for the fact that it is a client-server application, when the protocol you use is done sending the stuff over, the protocol will release it's reference and it will most likely kick in the garbage collector. Still: an experienced Java programmer would never write code like this. And: an experienced Java programmer would never NEED multiple return values.

Reply Score: 1

v.alexeev Member since:
2008-02-05

If you don't see a reason why I should use a wrapper object, then why don't you see a reason for multiple return values?
It is doing the exact same thing logically.

No and no. First - no sequence of variables covered in obscure "tuple". This defy the very basic ideas of OO programming like encapsulation. Second - I've suggested not a wrapper object but rather an entity on it's own aware of how to fetch the data, how is it encoded, how it needs to be pre-processed etc. This will allow you to decouple supplier from consumer.

It isn't often that I need to return multiple things. Hardly ever. I just mentioned one case where it made sense.

If I wanted to be "object oriented" using getters I could call one method compute() like so...

And the case may point out to a deeper design problem.
I suggest you look once again at each and every case you think you must use more then one return value and try to avoid this at all cost.

Reply Score: 1

not really
by ahmetaa on Thu 17th Jul 2008 18:17 UTC
ahmetaa
Member since:
2005-07-06

in Java, if you need multiple return values in your application "most of the time" it is an indication of bad design.

Reply Score: 2

RE: not really
by eggs on Thu 17th Jul 2008 20:22 UTC in reply to "not really"
eggs Member since:
2006-01-23

Yeah...

I do .Net in C# for my job which also doesn't allow multiple returns and I have never wished that I could return multiple values. I just make a struct.

I suppose I could also use output parameters (not sure if that is in Java), but they always seemed ugly to me.

Reply Score: 2

timneedscoffee80
Member since:
2008-07-17

I think it's pretty clear from reading this article that you have very little experience in solid object oriented design. No developer worth his salt would implement a generic "two return value" wrapper like that. If you have a set of related information that gets returned, the proper way to handle it is to design a class that represents that object, and contains methods to analyze its data.

The solution you suggest is an arbitrary pairing of potentially unrelated data in a too-generic fashion, from which no meaning can be derived - and is therefor a horrible design.

I may also point out that if you NEED multiple return values (which you don't, you want them, but noone ever needs them), and another languages supports them, then clealy Java was the wrong choice in the first place.

Reply Score: 5

YEPHENAS Member since:
2008-07-14

I think it's pretty clear from reading this article that you have very little experience in solid object oriented design. No developer worth his salt would implement a generic "two return value" wrapper like that. If you have a set of related information that gets returned, the proper way to handle it is to design a class that represents that object, and contains methods to analyze its data.

The solution you suggest is an arbitrary pairing of potentially unrelated data in a too-generic fashion, from which no meaning can be derived - and is therefor a horrible design.

Right. Classes like Point, PairOfShoes, Triangle, ... instead of TwoReturnValues and ThreeReturnValues. And if the values don't relate the method should get refactored.

Reply Score: 2

Comment by wigginz
by wigginz on Thu 17th Jul 2008 18:56 UTC
wigginz
Member since:
2006-03-03

Reading the RSS summary I was just going to say write a class that encapsulates all the data you want to return... problem solved. I Guess that's the solution you were advocating, never mind!

Reply Score: 2

Comment by YEPHENAS
by YEPHENAS on Thu 17th Jul 2008 19:21 UTC
YEPHENAS
Member since:
2008-07-14

Just introduce a new class.

As you said:

Java is object-oriented! If you are afraid of creating single objects then you shouldn't use Java at all.

And the next one will come along and demand more horrible things like out parameters, structs and pointers for Java.

Reply Score: 3

What's the purpose of a method?
by andyleung on Thu 17th Jul 2008 19:32 UTC
andyleung
Member since:
2006-03-24

I definitely second everybody who suggested that the author needs a better design rather than having the programming language to implement something non-sense.

If you need multiple return values, that means your method is coding too much logic into it and why don't you code everything in main and if that is the case, you don't need Java or even OO, just go back to any procedural language and even in those you only need main method.

A method (no matter it's in object or procedural) is a unit that serves a unique purpose. You code minimum logic into one method and this is why you unit test your method (some suggests you unit test on object, not method). A method is following a simple processing model:

Input->Process->Output

If you identify only one output and you will know what you need from input and process. In this case, if you need more than one return value, I guess you should start again to understand the fundamental of programming.

No offense but just my 2 cents.

:)

Reply Score: 5

Alternatives
by fretinator on Thu 17th Jul 2008 19:47 UTC
fretinator
Member since:
2005-07-06

If I understand, your main idea was to have a function return an object as well as some boolean status of success. Here are my alternatives.

1. Pass the object you want manipulated, and return a boolean. Example: boolean populateObject(ObjectRef objectToPopulate)

2. Return an object reference, and test for null. Example: ObjectRef populateObject(). A null return means it failed. This is one reason I rarely use int as a return, but instead use an Integer. Then I can just test for null.

3. The best approach to do what you want (have a function return both a value and some status flag) is to use exceptions. Example: ObjectRef populateObject() throws ObjectPopulationException. Then your external code would use a try/catch to call this function. This is the norm with languages that supports exception handling.

Just my 1/50th of a falling dollar.

Reply Score: 3

RE: Alternatives
by danieldk on Thu 17th Jul 2008 20:13 UTC in reply to "Alternatives"
danieldk Member since:
2005-11-18

1. Pass the object you want manipulated, and return a boolean. Example: boolean populateObject(ObjectRef objectToPopulate)


I usually try to avoid this, since Java does not codify your intention in the method signature. The obvious danger is that if it happens more than once in a library that you will confuse the library user. If it happens only a few times, you will suprise the user. It's a solution, but be careful!

Actually, I am happy C++ allows pass by value (where a value can also be a pointer), and pass by reference. If you really want to modify variables or instances provided through a parameter list, you can make this more explicit by using a pointer (without constness).

2. Return an object reference, and test for null. Example: ObjectRef populateObject(). A null return means it failed. This is one reason I rarely use int as a return, but instead use an Integer. Then I can just test for null.


That's usually not a good idea for math-intensive code due to all the boxing/unboxing that takes place. At other places this can be a good solution, if documented.

If the return type is a floating point type, and the parameters cause an invalid result, returning NaN is an option.

3. The best approach to do what you want (have a function return both a value and some status flag) is to use exceptions. Example: ObjectRef populateObject() throws ObjectPopulationException. Then your external code would use a try/catch to call this function. This is the norm with languages that supports exception handling.


Be careful there as well. Exceptions are for when... something exceptional happens. The danger is misusing exceptions as a mechanism to return values. Of course, Java does provide some good exceptions for common exceptional occasions. For those cases, prefer one of the exceptions that Java defines.

Edited 2008-07-17 20:21 UTC

Reply Score: 3

Be clear to the caller
by danieldk on Thu 17th Jul 2008 19:54 UTC
danieldk
Member since:
2005-11-18

From the article:

Having a solution alone is sometimes not enough and you also need to add some parameters which measure the quality of the computed outcome. Most of these accompanying parameters can or have to be computed within the algorithm itself, but Java allows you to return only one value either an object or a primitive type. [...] But as a Java programmer you are pretty much stuck here and need to consider some other means to come out of this situation.

Actually, you are mistaking a inherent property of Java and other static-typing languages as a disadvantage. If used properly, it is an advantage: the person implementing the caller code can exactly see by looking up the function or method declaration what to expect. This is a potential downside of dynamic languages, that can usually return anything, as long as it is (usually) a reference to something.

With the proposed solution, there's a risk of returning something that is potentially meaningless to the caller. Therefore, in such situations it's normally best to either: use more getters (where appropriate), or if the data in strongly coupled (which appears to be the case in the example mentioned in the article) return it as a class with its own getters.

Sure, there are situations where tuple-like classes can be useful. A good example is std::pair in C++, which is used for data stored within a map. The first element of the pair is used as the key, the second element as the value. Most if not all (since std::map provides ordering guarantees) implementations of std::map store these pairs in a binary tree that is ordered by the key. It's also convenient for iteration.

But for what my opinion is worth, this article makes a design error, it's the kind of approach you'll want to avoid in a static-typing OO language.

Reply Score: 3

Er... weak
by FreeGamer on Thu 17th Jul 2008 21:11 UTC
FreeGamer
Member since:
2007-04-13

Very weak argument.

You want multiple return values? Use an array, then you have as many return values as you like, no objects required.

Making Java as dynamic as JavaScript would be a mistake and it's this kind of dynamic feature creep that could lead to that.

Reply Score: 1

Think about you software design!
by Ralf. on Thu 17th Jul 2008 22:11 UTC
Ralf.
Member since:
2005-08-13

If you are in the need of returning more than one value by a method, you should probably think about your software design!

Reply Score: 2

easiest solution... Map
by Yamin on Thu 17th Jul 2008 23:10 UTC
Yamin
Member since:
2006-01-10

Man, do I hate complications.

If you really must have multiple return values, just use a map and return it. Better than that, you can have named values:

Map Foo()
{
Map ret = new Map;
Map["return1"] = X;
Map["return2"] = Y;
Map["return3"] = Z;

return ret;
}


There you go. Problem solved. BTW... I haven't used java in a while, so that may not be syntactically correct, but the point is the same ;)

If you think this is too slow due to the lookup, you can be annoying and use a Vector instead ;) .

So... why add more crap to a language?

Reply Score: 1

Common Lisp Usage
by malkia on Thu 17th Jul 2008 23:53 UTC
malkia
Member since:
2005-07-17

I think what the poster needs is really what's in Common-Lisp (I don't know whether something similar exists in other languages too).

Let's take as an example the standard floor mathematical function, that would return the integer portion (and in Common Lisp it might return additionally the remainder portion).

Normally people are only interested in getting the integer part, so all they are doing is this:

(setf some-var (floor some-other-var))

In "C" this would be:

some_var = floor( some_other_var );

The user is not even aware that floor can actually return two values, because it's still used as if it was returning one (in such cases the CL compiler might be smart enough and optimize it).

Now if you want 2 values to be returned - the integer part of floor, and the rational (floating in other languages) remainder, here's what you'll have to do:

;; Let's put in some-other-var the rational 3/2
(setf some-other-var 3/2)

;; Now get the two values
(multiple-value-bind (a b)
(floor some-other-var)
(format t "A=~a B=~a" a b))

---> A=1 B=1/2

The long-ish MVB multiple-value-bind form is going to assign local variable 'a' to 1 and 'b' to 1/2, format is printing them.

Documentation: http://www.lisp.org/HyperSpec/Body/mac_multiple-value-bind.html#mul...

In Common-Lisp there are 4 or 5 such operators specifically for getting multiple return values - some can accumulate the results directly in local variables, others in lists, etc.

Reply Score: 3

Comment by asgard
by asgard on Fri 18th Jul 2008 06:55 UTC
asgard
Member since:
2008-06-07

I am getting depressed from this discussion. All this "if you want to return multiple values, your design is wrong" nonsense. It's useful! Try it in Python, at least once.

The reason why Java (and C and it's predecessors) didn't support it is historical and comes from mathematics. In mathematics, functions that return multiple objects are useless, because you can just have multiple functions.

However, in programming, you often need to compute something and you get some other useful result as a side-effect of that computation. Classic example is the quotient/remainder example in the integer division. To split it into two functions, you would have to do the division twice, which would be silly. Sure, you can also wrap them into an object or struct or whatever, but compare this to Python, where you just "return them" and it's completely natural.

So please, stop saying that just because your language of choice doesn't support it, it's not useful. Because it is.

Reply Score: 6

RE: Comment by asgard
by nyarlathotep on Fri 18th Jul 2008 07:44 UTC in reply to "Comment by asgard"
nyarlathotep Member since:
2008-07-18

Classic example is the quotient/remainder example in the integer division. To split it into two functions, you would have to do the division twice, which would be silly. Sure, you can also wrap them into an object or struct or whatever, but compare this to Python, where you just "return them" and it's completely natural.


I don't see any problems in creating an object for that. Even if you think it will overhead, when you pass it as an arguments to another method, you'll find the object very usefull, because you only have manage one variable per result. Additionally I like the idea of not changing method signatures (and thus breaking backward compatibility), just because I need another argument.

Reply Score: 1

RE[2]: Comment by asgard
by asgard on Fri 18th Jul 2008 08:07 UTC in reply to "RE: Comment by asgard"
asgard Member since:
2008-06-07

I don't see any problems in creating an object for that.


Well, Python also creates an object (a tuple), so you can actually retrieve and manipulate the return values together. So this is a solved problem.

Anyway, my point is it's not always quite useful to define an object. In some cases yes, for example, if you have a point in 3D, then you probably want to have it as an object.

But in some cases, it is pointless to have an object "result of integer division". So why even bother?

Imagine a language where you can only have functions with one argument. Sounds silly? But it is exactly what you are defending. You could also say, well, you can always construct an object from the arguments, and it will be helpful in many cases. You could also say that it would be good because the function signature would never change.

In fact, I don't see any reason why it couldn't be completely symmetric. Thus, why cannot we have multiple return values, default return values, keyword return values and unlimited number of return values. The only reason I see is historic - we are used to notation that doesn't allow all of this stuff.

Reply Score: 2

RE[3]: Comment by asgard
by nyarlathotep on Fri 18th Jul 2008 15:02 UTC in reply to "RE[2]: Comment by asgard"
nyarlathotep Member since:
2008-07-18

Imagine a language where you can only have functions with one argument. Sounds silly?

At first glance, yes. But let's think this some further: Normally you just put "something" and "something" into a method and getting a "something" and maybe another "something" back. Like this:

(c,d) = divide(a,b);

If you find this call in a sourcecode: How do you know, what's the divisor, remainder, etc.? You have to look at the documentation and interpret the call.
Now imagine this example in a one-parameter-,one-return-value-language:

DivideParameter params = new DivideParameter();
params.dividend = a;
params.divisor = b;
DivideResult result = divide(params);
c = result.quotient;
d = result.remainder;

Ok, it's much more to code, but it's much easier to understand, without looking at the documentation.
A good solution in the middle of this, would be named parameters/return values, so you can easily see what's going in and out.
If you just want multiple "somethings" as return values, define the return value as Object[].

Reply Score: 1

RE[4]: Comment by asgard
by asgard on Fri 18th Jul 2008 15:38 UTC in reply to "RE[3]: Comment by asgard"
asgard Member since:
2008-06-07

So, you basically agree with me that the situation with input and output values is symmetric.

However, I don't agree that the second example you give is more readable. In a large program, every line and every technicality obscures the high-level structure. To show you the types of parameters of function you are looking at is a job for IDE or some source code browsing tool, and it should not be needed to write it up again and again endlessly in the source itself.

Reply Score: 1

Multiple Return Types??
by nyarlathotep on Fri 18th Jul 2008 07:24 UTC
nyarlathotep
Member since:
2008-07-18

Hi!

I'm in Java programming for 9 years now, but never really seen a problem with multiple return types.
Normally I would prefer the data object style to return multiple values, because the data returned from one method is often related. So the object groups the data and dealing with the related informations is much easier. Changing the information is much easier, too. Think about:
Position calculatePosition(), goTo(Position pos), runFrom(Position pos)...
instead of:
int[] calculationPosition(), goTo(int x, int y, int z), runFrom(int x, int y, int z)...

If the data one method returns is not related, you should double-check your code, because it smells (see "code smells").

/Nyarla

Reply Score: 1

I guess you never tried Python
by Glynser on Fri 18th Jul 2008 09:31 UTC
Glynser
Member since:
2007-11-29

All those who claim that it's "useless" have never tried Python. If Java would borrow Python's multiple return types, it would look like this:


public (String, int) findName(List<whatever> names)
{
String name;
int number;

// do some searching inside the list...
// ...

// finally return the name and the amount of
// data that has been searched through (just an example)

return (name, number);
}


String name, int number = getName(someList);

System.out.println("Found: " + name);
System.out.println("I had to search through " + number + " items");


Now tell me that ain't useful? Of course it's not something you need everyday (and it might really be bad design in many cases), but there are cases where you want to return two things that are not so closely connected to each other that they really belong into the same class.

I have used it in Python before and it's very useful. I wish Java had this.

Reply Score: 3

RE: I guess you never tried Python
by danieldk on Fri 18th Jul 2008 14:16 UTC in reply to "I guess you never tried Python"
danieldk Member since:
2005-11-18

All those who claim that it's "useless" have never tried Python.


Oh, please. ;)

Now tell me that ain't useful? Of course it's not something you need everyday (and it might really be bad design in many cases), but there are cases where you want to return two things that are not so closely connected to each other that they really belong into the same class.


Sure you can do the same thing. Return an immutable list of 'Object's. Because that's what Python actually does (it returns a tuple). That's different than allowing for multiple return types (viewed from a static language).

People don't do this, because it sacrifices type safety. Of course, you will have to cast it back to some class type to make its methods visible again. (And you can't apply some of the syntactic cleverness that some dynamic languages offer in the calling code.)

If you don't want to do that, you are picking the wrong language. Java is a statically typed language, Python is dynamically typed. If you want a dynamic language for a particular job, use a dynamic language. Don't expect a static language to act as a dynamic or vise versa.

Edited 2008-07-18 14:20 UTC

Reply Score: 2

RE: I guess you never tried Python
by andyleung on Sat 19th Jul 2008 13:34 UTC in reply to "I guess you never tried Python"
andyleung Member since:
2006-03-24

All those who claim that it's "useless" have never tried Python. If Java would borrow Python's multiple return types, it would look like this:


public (String, int) findName(List names)
{
String name;
int number;

// do some searching inside the list...
// ...

// finally return the name and the amount of
// data that has been searched through (just an example)

return (name, number);
}


String name, int number = getName(someList);

System.out.println("Found: " + name);
System.out.println("I had to search through " + number + " items");


Now tell me that ain't useful? Of course it's not something you need everyday (and it might really be bad design in many cases), but there are cases where you want to return two things that are not so closely connected to each other that they really belong into the same class.

I have used it in Python before and it's very useful. I wish Java had this.


First of all, I would like to give you a very basic exam on how to call a method:

String name, int number = getName(someList);


Where did you get that method from when your method defined before was findName(...)?

Besides, you really need to learn what is OO. Even this example is not enough to proof you have enough OO knowledge. Let's say your example is to show that customer name with total number searched. You create an object that wraps these two values and pass it back to the caller until you reach your "View" and show it. This is value object pattern and if you create Frontend application, this becomes, somehow in web sense, your "Model" in "MVC". Tell me, if you have 5 layers (caller methods) between this "findName()" method and the frontend. During development cycle your requirement is changed 3 times for return value to include "long searchedInMilliSeconds, int listSize", you have to change all 5 layers (may be more than 5 caller methods) because they all return multiple values. I don't think this makes any of sense.

In the end, if you like the way of returning multiple values, why do you want "List" as parameter? You simply extract all values from this list, pass them all as parameters like the following:

public (String, int) findName(String name1, String name2, String name3, String name4, String name5...[until all names are passed]){
...
}

If you really like this way of programming, then I guess you don't even need/like to use array. If this is the case you may want to find out where your strength is really in instead of programming.

Reply Score: 0

j-kidd Member since:
2005-07-06

You have never tried Python.

Reply Score: 1

Glynser Member since:
2007-11-29

Well, I am SOO sorry that I once wrote getName und once findName - this was an EXAMPLE, it's likely to make such a mistake if you're writing this stuff into that comment box here...


And don't tell me I don't know about OO. This actually hasn't got anything to do with OO, it's just a tiny, tiny EXAMPLE of why multiple return types CAN actually be useful, or - maybe better - how an actual implementation would look like in Java. Cases where it might actually be useful should be made up by everyone themselves, I think every programmer should have just about enough phantasy to do that.

And yes, it's not useful for EVERY case (remember the sentence: "When you've got a shiny new hammer, every problem looks like a nail"). But there ARE some cases where it is indeed useful.

Python implements that feature. What do you think is the justification for this - widely used - feature in this - widely used - language, if it ain't useful and hasn't got anything to do with OO and and and...

Also, it hasn't got anything to do with type safety (not sure if it was you who mentioned that or someone else), because as you can see in my example, it would be actually VERY typesafe indeed. Because the types "String" and "int" are actually written there. And if you would return some other stuff instead, a good compiler _might_ tell you about that. Yes, Python just returns tuples, but they can be immediately assigned to seperate values (JUST like in my Java example) and if it would be included into a statically typed language, who would claim that it would be necessary to use some kind of Tuple<Object, Object> internally? No one, because it would be bullshit. And I didn't say that either. It would be no problem for static types (JUST like in my Java example).

Reply Score: 1

Holy crap
by pel! on Fri 18th Jul 2008 10:40 UTC
pel!
Member since:
2005-07-07

People should really spend more time with the fundamental parts of computing.

For instance - there is a HUGE cluebyfour in understanding the fundamental parts of LISP (S-expressions).

If someone, for an instance of a second, thought that this was a real problem with Java they should take a break and google up some fundamental LISP-knowledge and be a lot wiser.
As an added benefit you'll understand why those LISP/Scheme nutters (they are, really) are correct when they say that their language is beautiful.

Reply Score: 1

Nice discussion :)
by raupach on Fri 18th Jul 2008 11:20 UTC
raupach
Member since:
2008-07-18

Maybe I better clearify some parts.. Some claiming it is bad design. Could be, but design is always nice in theory but hard in practice. The intention of this article was for cases when multiple values are needed. I agree when implementing some UI, stuff like this is a bloat. But when using (misue) a language like Java for say number crunching algorithms the algorithms are itself messy and hard to read. There is no good design just from the beginning. Asgard gave a example. Do stuff like linear integer programming, data mining and you want multiple return values. One could argue: Why then Java? - use Matlab or Lisp. Yeah sure, I would like to. But sometimes the decisions are not yours to make and you have to reuse stuff your colleagues worked with.

Reply Score: 1

Right tool, right job
by sorpigal on Fri 18th Jul 2008 11:21 UTC
sorpigal
Member since:
2005-11-02

Multiple return values are fantastic, but Java as a language doesn't really need them. It's built in a way that demands their absence.

I'm primarily a Perl hacker but I've done some lisp, too. It's not really about returning two things from a function, it's about the way your code is structured.

In Java of course you'd just wrap things in an object. Preferably your code would not suck and the things would be related.

Reply Score: 2

C#
by Gryzor on Fri 18th Jul 2008 14:28 UTC
Gryzor
Member since:
2005-07-03

In C#.NET you could do…

SomeObject one = new SomeObject();
SomeObject two = new SomeObject();

private void ReturnTwo( out SomeObject objone, out SomeObject objtwo )
{
objone = whatever;
objtwo = whatevertwo;
}

(It's been a while since i used c# tho… but there was out and ref, out needed the parameter pre-initialized and ref allows you to initialize it inside the meethod)

Or something like that.

Reply Score: 2

RE: C#
by Gryzor on Fri 18th Jul 2008 14:29 UTC in reply to "C#"
Gryzor Member since:
2005-07-03

I think it is about time OSNews supports Unicode properly.

Reply Score: 2

How about a Pointer object
by Tron on Sat 19th Jul 2008 00:33 UTC
Tron
Member since:
2005-07-07

How about simulating a C pointer with an object? Then you can do it just like the C people do it.

public class Pointer<T> {
public Pointer(T val) {
value=val;
}
public T value;
}


Pointer<Type1> a;
Pointer<Type2> b;
myfun(a, b);

public void myfun(Pointer<Type1> a, Pointer<Type2> b) {
a = null;
b = new Pointer<Type2>(new Type2()));

}

Reply Score: 1

RE: How about a Pointer object
by Tron on Sat 19th Jul 2008 04:46 UTC in reply to "How about a Pointer object"
Tron Member since:
2005-07-07

Sorry for replying to myself, but the preview doesn't seem to work quite right with angle brackets.
Let's try this again:

public class Pointer<T> {
public Pointer(T val) {
value=val;
}
public T value;
}


Pointer<Type1> a;
Pointer<Type2> b;
myfun(a, b);

public void myfun(Pointer<Type1> a, Pointer<Type2> b) {
a = null;
b = new Pointer<Type2>(new Type2()));

}

Reply Score: 1

The Scala way
by John Nilsson on Sat 19th Jul 2008 13:40 UTC
John Nilsson
Member since:
2005-07-06

Scala solves this in a manner that actually preserves the nice design principle.

Here's an example:

object MultipleReturnValues extends Application {

// Define a class for the return value
case class RetVal(intPart: Int, fracPart: Double)

// Define a function returning values of that type
def floor(value: Double) : RetVal = new RetVal(value.floor.toInt, value - value.floor)

// Extract the parts of the return value and declare vals to hold them
val RetVal(i,f) = floor(10.4)

// Print the result
Console.println(i + " " + f)
}

The nice thing with scala is that it can easily be mixed with Java code.

Reply Score: 2