Tell me more ×
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.

Is there a reason or an explanation why functions in most(?) programming languages are designed to support any number of input parameters but only one return value?

In most languages, it is possible to "work around" that limitation, e.g. by using out-parameters, returning pointers or by defining/returning structs/classes.
But it seems strange, that programming languages were not designed to support multiple return values in a more "natural" way.

share|improve this question
15  
cause you can return an array... – nathan hayfield Jul 2 at 22:55
4  
So why not only allow one argument? I suspect it's tied to speech. Take some ideas, smoosh 'em into one thing that you return to whoever's fortunate/unfortunate enough to be listening. The return is almost like an opinion. "this" is what you do with "these." – Erik Reppen Jul 3 at 2:48
7  
I believe python's approach is quite simple and elegant: when you have to return multiple values simply return a tuple: def f(): return (1,2,3) and then you can use tuple-unpacking to "split" the tuple: a,b,c = f() #a=1,b=2,c=3. No need to create an array and manually extract elements, no need to define any new class. – Bakuriu Jul 3 at 7:40
3  
I can inform you that Matlab has a variable number of return values. The number of output arguments is determined by the calling signature (e.g. [a, b] = f() vs. [a, b, c] = f()) and obtained inside f by nargout. I'm not a big fan of Matlab but this actually comes in quite handy at times. – gerrit Jul 3 at 10:06
2  
I think if most programming languages are designed that way is debatable. In the history of programming languages, there were some very popular languages created that way (like Pascal, C, C++, Java, classic VB), but today there are also a hell lot of other languages getting more and more fans which allow multiple return values. – Doc Brown Jul 3 at 16:34
show 2 more comments

10 Answers

Because functions are mathematical constructs which perform a calculation and return a result. Indeed, much of "under the hood" of not a few programming languages focus solely on one input and one output, with multiple inputs being a thin wrapper around the inputs.

This has not changed because programmers have found out parameters to be awkward constructs that are useful in only a limited set of scenarios. Like with many other things, the support isn't there because the need/demand isn't there.

share|improve this answer
4  
@FrustratedWithFormsDesigner - this came up a little bit in a recent question. I can count on one hand the number of times I wanted multiple outputs in 20 years. – Telastyn Jul 2 at 21:26
17  
Functions in Mathematics and functions in most programming languages are two very different beasts. – tdammers Jul 2 at 21:50
4  
@tdammers in the early days, they were very similar in thought. Fortran, pascal and the like where heavily influenced by math more than computing architecture. – MichaelT Jul 2 at 22:00
2  
@tdammers - how so? I mean for most languages it boils down to lambda calculus in the end - one input, one output, no side effects. Everything else is a simulation/hack on top of that. Programming functions might not be pure in the sense multiple inputs may yield the same output but the spirit is there. – Telastyn Jul 2 at 22:11
3  
Most programming languages allow functions like rand() or time() which aren't functions in the mathematical sense. – dan04 Jul 3 at 0:21
show 11 more comments

In mathematics, a "well-defined" function is one where there is only 1 output for a given input (as a side note, you can have only single input functions, and still semantically get multiple inputs using currying).

For multi-valued functions (eg. squared root of a positive integer, for example), it's sufficient to return a collection, or sequence of values.

For the types of functions you're talking about (ie. functions that return multiple values, of different types) I see it slightly differently than you seem to: I see the need/use of out params as a workaround for better design or a more useful data structure. For example, I'd prefer if *.TryParse(...) methods returned a Maybe<T> monad instead of using an out param. Think of this code in F#:

let s = "1"
match tryParse s with
| Some(i) -> // do whatever with i
| None -> // failed to parse

Compiler/IDE/analysis support is very good for these constructs. This would solve much of the "need" for out params. To be completely honest, I can't think of any other methods off-hand where this wouldn't be the solution.

For other scenarios - the ones I can't remember - a simple Tuple suffices.

share|improve this answer
1  
In addition, I would really like to be able to write in C#: var (value, success) = ParseInt("foo"); which would be compile-time type checked because (int, bool) ParseInt(string s) { } was declared. I know this can be done with generics, but still it would make for a nice language addition. – Grimace of Despair Jul 3 at 12:30
4  
@GrimaceofDespair what you really want is destructuring syntax, not multiple return values. – Domenic Jul 3 at 18:39
Ok, let's vote then :P connect.microsoft.com/VisualStudio/feedback/details/371895/… ... oh, it's already closed as "Won't fix" :D – Grimace of Despair Jul 4 at 7:02
random question - does that make the function that solves a quadratic equation not "well-defined" because it returns a plus/minus value? – warren Jul 8 at 19:31
1  
@warren: Yes. See here and note that such a solution would not be continuous: en.wikipedia.org/wiki/Well-definition – Steve Evers Jul 8 at 21:24

Some languages, like Python, support multiple return values natively, while some languages like C# support them via their base libraries.

But in general, even in languages that support them, multiple return values are not used often because they're sloppy:

  • Functions that return multiple values are hard to name clearly.
  • It's easy to mistake the order of the return values

    (password, username) = GetUsernameAndPassword()  
    

    (For this same reason, many people avoid having too many parameters to a function; some even take it as far as to say a function should never have two parameters of the same type!)

  • OOP languages already have a better alternative to multiple return-values: classes.
    They're more strongly-typed, they keep the return values grouped as one logical unit, and they keep the names of (properties of) the return values consistent across all uses.

The one place they are pretty convenient is in languages (like Python) where multiple return values from one function can be used as multiple input parameters to another. But, the use-cases where this is a better design than using a class are pretty slim.

share|improve this answer
13  
Its hard to say that returning a tuple is returning multiple things. Its returning one tuple. The code you've written just unpacks it cleanly using some syntactic sugar. – Lego Stormtroopr Jul 2 at 23:27
8  
Its a really hazy distinction, but consider an empty Tuple (). Is that one thing or zero things? Personally, I would say its one thing. I can assign x = () just fine, just like I can assign x = randomTuple(). In the latter if the returned tuple is empty or not, I can still assign the one returned tuple to x. – Lego Stormtroopr Jul 2 at 23:46
3  
...I never claimed that tuples couldn't be used for other things. But arguing that "Python does not support multiple return values, it supports tuples" is simply being extremely pointlessly pedantic. This is still a correct answer. – BlueRaja - Danny Pflughoeft Jul 3 at 3:25
1  
A tuple, or any structured grouping, is different because it expresses a valid, innate relationship between the distinct [primitive] values, even if the relationship is tenuous. – JustinC Jul 3 at 16:45
2  
Neither tuples nor classes are "multiple values". – Andres F. Jul 3 at 17:25
show 5 more comments

In addition to what's already been said when you look at the paradigms used in assembly when a function returns it leaves a pointer to the returning object in a specific register. If they used variable/multiple registers the calling function would not know where to get the returned value(s) if that function was in a library. So that would make linking to libraries difficult and instead of setting an arbitrary number of returnable pointers they went with one. Higher level languages don't quite have the same excuse.

share|improve this answer
Ah! Very interesting point of detail. +1! – Steve Evers Jul 2 at 22:02
This should be the accepted answer. Usually people think about target machines when they built compilers. Another analogy is why we have int, float, char/string, etc. because that's what's supported by target machine. Even if the target is not bare metal (e.g. jvm), you still want to get decent performance by not emulating too much. – imel96 Jul 2 at 22:34
17  
...You could easily define a calling convention for returning multiple values from a function, in nearly the same way you can define a calling convention for passing multiple values to a function. This is not an answer. -1 – BlueRaja - Danny Pflughoeft Jul 2 at 22:40
I do not agree this should be THE accepted answer, but I agree it is a good detail to know, and to add to the answer(s): it is a fact that common calling conventions on common architectures use a register (EAX in x86) for returning values to the caller. Different calling conventions are possible, of course, but... – Lorenzo Dematté Jul 5 at 6:58
It would be interesting to know if stack-based execution engines (JVM, CLR) have ever considered/permitted multiple return values.. it should be quite easy; the caller just have to pop the right number of values, just like it pushes the right number of arguments! – Lorenzo Dematté Jul 5 at 7:02
show 1 more comment

In most languages where functions are supported you can use a function call anywhere where a variable of that type can be used:-

x = n + sqrt(y);

If the function returns more than one value this will not work. Dynamically typed languages such as python will allow you to do this, but, in most cases it will throw up a run time error unless it can work out something sensible to do with a tuple in the middle of an equation.

share|improve this answer
1  
Just don't use inappropriate functions. This is no different from the "problem" posed by functions that return no values, or return non-numeric values. – ddyer Jul 3 at 4:27
1  
In languages I've used that do offer multiple return values (SciLab, for example), the first return value is privileged, and will be used in cases where only one value is needed. So no real problem there. – The Photon Jul 3 at 4:45

It does complicate the syntax a little, but there's no good reason at the implementation level not to allow it. Contrary to some of the other responses, returning multiple values, where available, leads to clearer and more efficient code. I can't count how often I have wished I could return an X and a Y, or a "success" boolean and a useful value.

share|improve this answer
2  
Could you provide an example of where multiple returns provide clearer and/or more efficient code? – Steve Evers Jul 2 at 22:05
3  
For example, in C++ COM programming, many functions have one [out] parameter, but virtually all return an HRESULT (error code). It would be quite practical to just get a pair there. In languages which have good support for tuples, such as Python, this gets used in a lot of code I have seen. – Felix Dombek Jul 2 at 22:08
In some languages, you'd return a vector with the X and Y coordinate, and returning any useful value would count as "success" with exceptions, possibly carrying that useful value, being used for failure. – Jonathan Hobbs Jul 2 at 22:09
2  
Lots of the time you end up encoding information into the return value in non-obvious ways - ie; negative values are error codes, positive values are results. Yuk. Accessing a hash table, it's always messy to indicate if the item is was found and also return the item. – ddyer Jul 2 at 23:11
@SteveEvers The Matlab sort function normally sorts an array: sorted_array = sort(array). Sometimes I also need the corresponding indices: [sorted_array, indices] = sort(array). Sometimes I only want the indices: [~, indices] = sort(array). The function sort` can actually tell how many output arguments are needed, so if additional work is needed for 2 outputs compared to 1, it can calculate those outputs only if needed. – gerrit Jul 3 at 10:13
show 2 more comments

A lot of the use cases where you would have used multiple return values in the past simply aren't necessary anymore with modern language features. Want to return an error code? Throw an exception or return an Either<T, Throwable>. Want to return an optional result? Return an Option<T>. Want to return one of several types? Return an Either<T1, T2> or a tagged union.

And even in the cases where you genuinely need to return multiple values, modern languages usually support tuples or some kind of data structure (list, array, dictionary) or objects as well as some form of destructuring bind or pattern matching, which makes packaging up your multiple values into a single value and then destructuring it again into multiple values trivial.

Here are a few examples of languages that do not support returning multiple values. I don't really see how adding support for multiple return values would make them significantly more expressive to offset the cost of a new language feature.

Ruby

def foo; return 1, 2, 3 end

one, two, three = foo

one
# => 1

three
# => 3

Python

def foo(): return 1, 2, 3

one, two, three = foo()

one
# >>> 1

three
# >>> 3

Scala

def foo = (1, 2, 3)

val (one, two, three) = foo
// => one:   Int = 1
// => two:   Int = 2
// => three: Int = 3

Haskell

let foo = (1, 2, 3)

let (one, two, three) = foo

one
-- > 1

three
-- > 3

Perl6

sub foo { 1, 2, 3 }

my ($one, $two, $three) = foo

$one
# > 1

$three
# > 3
share|improve this answer
I think one aspect is that, in some languages (such as Matlab), a function can be flexible in how many values it returns; see my comment above. There any many aspects in Matlab I don't like, but this is one of the few (perhaps the only) feature I miss when porting from Matlab to e.g. Python. – gerrit Jul 3 at 10:08
@gerrit: this could be solved with overloading. A function which returns a 4-tuple is a different type than a function which returns a 5-tuple. So, you do not necessarily need multiple returns for this, however multiple returns seem to be more common than overloading based on return type. – Jörg W Mittag Jul 3 at 10:12
But what about dynamic languages like Python or Ruby? Suppose I write something like the Matlab sort function: sorted = sort(array) returns only the sorted array, whereas [sorted, indices] = sort(array) returns both. The only way I can think of in Python would be to pass a flag to sort along the lines of sort(array, nout=2) or sort(array, indices=True). – gerrit Jul 3 at 10:17
@gerrit: True, if the type information isn't there, then there's nothing you can do about it. – Jörg W Mittag Jul 3 at 15:16
@gerrit IMO, if the function can return arbitrarily many values, then it should return a list. If the function can return a fixed variation of values, I guess it has a return type somewhat like 2Values | 3Values | 5Values, which can -- and should -- be pattern-matched. – Andres F. Jul 3 at 17:31

At least the functional languages I know return multiple values straightforwardly without any need of workarounds by tuples (in dynamically typed languages you can use even lists) - also supported by other languages:

f :: Int -> (Int, Int)
f x = (x - 1, x + 1)

// Even C++ have tuples - see Boost.Graph for use
std::pair<int, int> f(int x) {
  return std::make_pair(x - 1, x + 1);
}

In example above the f is a function returning 2 ints.

Similarly ML, Haskell, F#, ... can return data structures as well (pointers are too low-level for most languages). Similarly I have not heard about modern GP language with such restriction:

data MyValue = MyValue Int Int

g :: Int -> MyValue
g x = MyValue (x - 1, x + 1)

Finally the out parameters can be emulated even in functional languages by IORef. There are several reasons why there is no native support for out variables in most languages:

  • Unclear semantic. If you have following function is the 0 or 1 printed? I know languages which would print 0 and ones that would print 1 and there are benefits (both in terms of performance as well as matching programmers mental model) to both of them:

    int x;
    
    int f(out int y) {
      x = 0;
      y = 1;
      printf("%d\n", x);
    }
    f(out x);
    
  • Non-localized effects. As in example above you can find that you can have a long chain and the innermost function affects the global state. In general it makes it harder to reason what are requirements of function and if the change is legal. Given that most modern paradigms try to either localize the effects (encapsulation in OOP) or eliminate the side-effects (functional programming) it is against those paradigms.

  • Being redundant. If you have tuples you have 99% of usage of out parameters and 100% of idiomatic use. If you add pointers to the mix you cover the remaining 1%.

I have troubles naming one language which could not return multiple values by tuple, class or out (and in most cases 2 or more of those methods are allowed).

share|improve this answer
+1 For mentioning how functional languages handle this in an elegant & painless way. – Andres F. Jul 3 at 17:29
Technically you are still returning a single value still :D (It's just that this single value is trivial to decompose into multiple values). – Thomas Eding Jul 12 at 21:39
@ThomasEding: Technically I can also imagine having one argument (a tuple) which just is constructed behind the scene - the 'technically' here is just a naming. My guess is that such distinction is meaningless once you try to formalize it. – Maciej Piechotka Jul 12 at 22:43

Well Ruby let your return an array into values, as is:

def aa(value) 
  return [a,b,c] # An array
end

and you can also receive the values straight into a,b,c = aa(20)

share|improve this answer

One aspect not yet mentioned: in the early days Memory was precious and limited and more return values implied more memory to consume.

share|improve this answer

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.