4

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

  • 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
  • 4
    Returning multiple values – AngryBird Jul 26 '11 at 19:04
  • 1
    A perfect example is when you are returning coordinates return x, y, z – CaffGeek Jul 26 '11 at 21:02
  • 7
    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
  • 1
    Just a comment, in python there is no such a thing as returning multiple values. The return value is one and only one (even if you don't return anything). If you can "return multiple values" is because you are actually returning a tuple, which optionally can be unpacked at the function call place, or left as a tuple. – bgusach Nov 3 '14 at 11:22
13

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.

  • 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
6

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.

4

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:
  • 3
    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
  • 2
    @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
3

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? :)

3

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.

2

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.

1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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