Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I feel as if a return statement should only return one value. When it returns multiple, things get confusing. I know since the return type in Java has to be declared, this is difficult to do, but in languages like Python it is a snap.

Are multiple return values a sign of bad design or coding style?

Python example


def get_name():
   # you code
   return first_name, last_name

share|improve this question
1  
Are you asking about returning multiple values at the same time? Different values in different branches of control flow? Different types depending on some condition? It's hard to tell. –  C. A. McCann Jul 26 '11 at 18:58
    
Could you please give a clear and concise code sample(s) to explain what you mean? –  FrustratedWithFormsDesigner Jul 26 '11 at 18:59
    
Can you show me an example of a return statement returning multiple values? –  Rein Henrichs Jul 26 '11 at 19:00
3  
Returning multiple values –  AngryBird Jul 26 '11 at 19:04
6  
Haven't you ever had something return a struct? That's essentially the same as multiple return values. –  whatsisname Jul 26 '11 at 21:13
show 2 more comments

7 Answers

up vote 13 down vote accepted

It's not a sign of anything, and is not neither good nor bad design or coding style.

Returning multiple values can actually be appropriate and allow to write less code. Let's take an example of a method which takes a string like "-123abc" and converts it to an integer like -123:

(bool, int) ParseInteger(string text)
{
    // Code goes here.
}

returns both:

  • a value indicating whether the operation was a success,
  • the number converted from string.

How can we refactor this?

1. Exceptions

We can add exceptions, if the language supports them. Remember than in most languages, exceptions are expensive in resources. It means that if you have to deal with lots of non-numbers, it's better to avoid to throw an exception every time the string cannot be converted to a number.

2. New class

We can create a class and return an instance of an object of this class.

For example:

class ParsedInteger
{
    bool IsSuccess { get; set; }
    int Number { get; set; }
}

Is it easier to understand? Shorter to write? Does it bring anything? I don't think so.

3. Out parameters

If the language supports it, we can also use out parameters. This is the approach of C# where returning multiple values is not possible. For example, when parsing a number, we use: bool isSuccess = int.TryParse("-123abc", out i). I'm not sure how is it better to use out parameters compared to multiple values. The syntax is not obvious, and even StyleCop itself (the tool used to enforce the default Microsoft style rules on the code) complains about those parameters, suggesting to remove them when possible.


Finally, in languages as C# where there is no such a thing as returning multiple values, things are progressively added to imitate the behavior. For example, Tuple was added to allow returning several values without having to write your own class or use out parameters.

share|improve this answer
1  
+1: "It's not a sign of anything." It is an option. The option you pick should depend on the information you are trying to return. –  unholysampler Jul 26 '11 at 19:29
1  
+1 I hate using out parameters because it's much less intuitive to track a reference throughout the code block. Also, it's pretty common practice to assume that a returned value means success (and a -1 is a failure) but your example using a tuple perfectly illustrates where both results can be checked without requiring any assumptions about the internal implementation. We could probably fix a lot of potential bugs if we just made a commitment to quit using (1 == !undefined||true||success) and (-1 == undefined||false||failure); the grandaddy of leaky abstractions. –  Evan Plaice Jan 17 '12 at 5:14
add comment

Perhaps you would be better off to encapsulate these values into an object - since who knows when you'll decide to return even more data, right? :)

share|improve this answer
add comment

I'm assuming you're talking about returning something like a tuple, object, or other composite data structures. Using them can often make a program more clear, but you have to be careful about cohesion and coupling. I've seen instances where a huge data structure is being passed around that could easily be replaced by globals, when different parts of the code should have been responsible for small, consistent pieces of it.

share|improve this answer
add comment

Well, I hope it's not a sign of bad design or coding style as it's common in the built in libraries. Your example of first_name, last_name looks perfectly reasonable to me. Once you go beyond a few reasonable and related values though, it probably makes sense to look into other alternatives so as to avoid returning a huge list of positional values.

share|improve this answer
add comment

No, I don't think you can declare this to be bad style just because you think it's 'confusing'. Actually, why should it be more confusing than having multiple parameters when calling the function. It's more what you are used to and if you use it often enough, you won't find it difficult anymore.

share|improve this answer
add comment

When your function returns a reference to an object that contains multiple members, is it returning one value or many? In the example you show, the function is actually returning an object of type tuple. Python just happens to support syntactic 'sugar' so that you don't have to explicitly dereference the members when making assignments from the return value of the function.

share|improve this answer
add comment

Well, I've seen this recently:

current_pixel = pixel[x,y]
# Formula for Orange: 50% red and more green than blue
if float(current_pixel[0])/(current_pixel[0]+current_pixel[1]+current_pixel[2]+1)>0.5 and current_pixel[1]>current_pixel[2]:

And here's the sane way to do it:

red, green, blue = pixel[x,y]
if green > blue and float(red) / (red + green + blue + 1) > 0.5:
share|improve this answer
2  
If you had a pixel object with pixel.red, pixel.green, pixel.blue, this would be even more clear - no way to mix the order of the pixel's components. –  Paŭlo Ebermann Jul 26 '11 at 22:06
1  
@Paŭlo Ebermann Isn't the relationship above clear enough to intuit. What value do you add to the codebase by including more boilerplate? Where does the structure go? Is it's functionality tested? In statically typed languages like C# where boilerplate is the glue that holds everything together a class-based approach is perfectly acceptable. In dynamically typed languages it's more difficult to track errors so the simplicity adds value. –  Evan Plaice Jan 17 '12 at 5:04
    
@Paŭlo Ebermann: It's because the library (PIL) works that way. But you're correct. Would it be my own library, it'd probably have a Pixel class. –  pillmuncher Mar 4 '12 at 0:55
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.