

Why do most programming languages only return a single value from a function? - wrongc0ntinent
http://arstechnica.com/information-technology/2013/12/why-do-most-programming-languages-only-return-a-single-value-from-a-function/

======
ced
Common Lisp has multiple return values and it's quite useful:

    
    
       (let x (f 12) ...)  ; bind x to the first value returned by (f 12) and silently drop the others
    
       (let (x y) (f 12) ...) ; bind x to the first value and y to the second. 
    

That way, I can return more information without breaking existing code. That
point is really important: in Python I can gracefully add an extra argument,
from

    
    
       def foo(x):
           ...
    

to

    
    
       def foo(x, y=None):
           ...
    

but I can't return an extra value without changing (and uglifying!) all
calling code to handle the tuple.

The answer to the OP is probably that all computer languages derive from
Fortran, and Fortran derived from maths, so it chose f(x, y) as the notation
for function application. With that notation, there's no elegant way of
handling more return values, and language designers might feel that the extra
complexity/ugliness isn't worth it. That, and intellectual inertia.

~~~
informatimago
Those let forms ares not Common Lisp. However, they could be mplemented by a
user with a lisp macro.

------
computer
Link to the actual page, instead of the blogspam version:
[http://programmers.stackexchange.com/questions/203471/why-
do...](http://programmers.stackexchange.com/questions/203471/why-do-most-
programming-languages-only-support-returning-a-single-value-from-a-f)

~~~
Argorak
I am not sure whether I would call this specific instance blogspam. It is a
curated series arstechnica runs together with stackoverflow that presents the
most interesting excerpts.

~~~
oneeyedpigeon
It's pretty worthless, whatever you choose to call it. For one, it adds
nothing to the original SO page - no commentary, insight, etc. For another, it
doesn't update dynamically, so is already out of date. It's now just
duplicating information that will no doubt be refined, so is pretty much
having a net-negative effect - exactly the kind of content SO was originally
set up to improve upon / obsolete.

~~~
malnourish
I'm unfortunately finding Ars more and more like this. Where I once went for
novel tech insight and reviews, I now see posts ''curated'' from around the
web, and a growing lifehacker-esque quality.

~~~
eli
Curation is fine, it's hyperbolic posts like this one [1] that appear to value
publishing first of getting it right.

[1]
[https://news.ycombinator.com/item?id=6896378](https://news.ycombinator.com/item?id=6896378)

------
slashnull
The given answer is a hack.

The real answer is "most languages _can_ return multiple values", since
whenever structs were introduced. And if you're bugged by the fact that there
are multiple input parameters, well, just think of the list of params as a
tuple. Which you could picture as anonymous structs anyways.

So that in the end, all functions take one tuple and return one tuple, where
tuples can be called structs, classes, or, well, tuples.

The _real_ question being, why is it that there is a syntactic sugar for
anonymous _input_ structs but that the sugar for _output_ structs is just
being introduced.

And there I have to admit I have no idea why.

------
asolove
A proof by contradiction:

Assume a language where functions do not only return one value. Now, consider
each function in this language. It either returns the same number of values
each time, where each has a specific meaning, and they are distinguished
either by order or by name. Or it returns an arbitrary number of values, where
the semantics of each are the same. But that means the return values are
equivalent to a tuple, a dictionary, or an array, which are single values.
Therefore we have a contradiction and such a language does not exist. (Yes, I
know about values in Lisp and this can be a bit nice. Mostly joking.)

More seriously, ask the question: what relationship between multiple values is
useful for returning from functions but not useful enough to be a data
structure that can be used in other parts of code?

~~~
kerkeslager
> More seriously, ask the question: what relationship between multiple values
> is useful for returning from functions but not useful enough to be a data
> structure that can be used in other parts of code?

Sometimes there are pieces of data which are hard to create a cohesive type
around. That is, you can compose an new type from other types, but you can't
really add any behavior to that new type. This is exemplified by the Tuple
type in many languages: it's basically a hack to treat disparate pieces of
data as one, and it doesn't offer any way to operate on its own data.

Here's an example from a relatively typical idiom of parsing an int from a
string:

    
    
        int parsedInt;
        if(int.TryParse(s, out parsedInt))
        {
            Console.WriteLine("Parsed {0}",parsedInt);
        }
        else
        {
            Console.WriteLine("{0} was not an integer",s);
        }
    

The problem here is that TryParse() really returns two values, one of which
will be tested to see if the parse was successful, and the other of which is
assigned to parseInt. You could test that the string can be parsed and then
get the parsed value in two separate functions, but this would be inefficient
because you'd essentially have to parse the string twice. I'm on my Mac so I'm
not sure I'm remembering this correctly, but I think C# forces you to put the
"out" there, which I think is good because it clarifies that parsedInt will be
assigned. However, I think there are a number of ways in which the following
(hypothetical) redefinition of TryParse (and C# syntax) feels a lot clearer:

    
    
        var parseSucceeded, parsedInt = int.TryParse(s);
    
        if(parseSucceeded)
        {
            Console.WriteLine("Parsed {0}",parsedInt);
        }
        else
        {
            Console.WriteLine("{0} was not an integer",s);
        }
    

First of all, the programmer has been forced to assign the success boolean to
a clarifying variable. Second, the call has a clearer structure: the input are
on the right side of the = and the outputs are on the left.

Let's look at some other possible solutions here:

    
    
        var parseTuple = int.TryParse(s);
    
        if(parseTuple.Item1)
        {
            Console.WriteLine("Parsed {0}",parseTuple.Item2);
        }
        else
        {
            Console.WriteLine("{0} was not an integer",s);
        }
    

This results in some confusing code. Item1 and Item2 are very poor names for
the things they represent.

    
    
        IntegerParseResult parseResult = int.TryParse(s); // Didn't use var here to clarify what this code means.
    
        if(parseResult.ParseSucceeded)
        {
            Console.WriteLine("Parsed {0}",parseTuple.ParsedInt);
        }
        else
        {
            Console.WriteLine("{0} was not an integer",s);
        }
    

This is a little better, but the creation of a whole new type seems
heavyweight, especially given that this new type provides no real
functionality. It's tying together two pieces of data which are about to be
separated and never used together again (consider, for example, that instead
of printing to the console it might return).

I guess the argument I'm making here is that just because a function returns
to outputs doesn't mean those outputs have a meaningful relationship that
would justify having a new type.

~~~
derleth
I think that's a bad example, because your TryParse function can be thought of
as returning a value wrapped in a monad. A Maybe monad, to be specific. In
Haskell:

    
    
        case (tryParse s) of 
          Just n -> putStrLn "Parsed " ++ (show n)
          Nothing -> putStrLn (s ++ " was not an integer")
    

Nothing is a very convenient little concept: It's a value which isn't a
'legitimate' value in any context. It's always a flag value. In C, for
example, there's no way to have a flag value of type int in this context,
because tryParse could conceivably return any value of type int as its
legitimate result. It's also wonderfully conceptually clean: The function
either just returns a legitimate value or it returns nothing legitimate at
all, and you always know which it did. The point is, however, it only returns
_one_ value, and doesn't rely on any out-of-band communications through errno
or similar.

If you want to get fancy, you can use the Either monad. This can allow you to
say _why_ a parse failed, for example:

    
    
        case (tryParse s) of
          Left n -> putStrLn "Parsed " ++ (show n)
          Right m -> putStrLn "Parse of " ++ s ++ " failed because " ++ m
    

In this case, tryParse would have the type:

    
    
        tryParse :: String -> Either Int String
    

The point here is, you still only return one value, but they can be either of
two different _kinds_ of value, as distinguished by being tagged either Left
or Right, and can even be different types. Again, one value, no out-of-band
signalling.

And, of course, Haskell has tuples. You can do interesting things without
them, however.

~~~
ufmace
C# has kind of an equivalent of that, at least for this purpose, of nullable
value types. Thus, you could do:

    
    
        int? result = int.TryParse(s);
    
        if(result.HasValue)
        {
            Console.WriteLine("Parsed {0}",result.Value);
        }
        else
        {
            Console.WriteLine("{0} was not an integer",s);
        }
    

And in C#, you could do the second kinda like:

    
    
        object result = int.TryParse(s);
    
        if(result is int)
        {
            Console.WriteLine("Parsed {0}",result);
        }
        else
        {
            Console.WriteLine("{0} was not an integer",s);
        }
    

Though there's nowhere simple to make it clear that this TryParse either
returns the parsed int, or a string describing why the parse failed. And
returning object kinda goes against the spirit of the language, IMHO.

------
rayiner
The stated reasons are all stupid. The real answer is likely that programming
language design is largely a cargo cult exercise and early languages only had
single return values, which are easier to implement.

~~~
freyrs3
Considering there's an entire academic discipline of programming theory I
strongly disagree with the description of language design as "cargo-cultism".

~~~
zzzcpan
It is considered cargo-cultism mostly because none of the languages ever have
any scientific data to support decisions on various syntax choices. There are
some very obvious bad choices of course, because of the large amount of bugs
involving them, like manual memory management and pointer arithmetic, but
other than that it's all just a hunch.

~~~
djur
Cargo-cultism is the duplication of the appearance of functioning systems or
structures in a context where they are nonfunctional or incorrectly
functional. Copying the functionality of an existing system isn't a cargo
cult.

The persistence of features in programming languages you're describing isn't a
cargo cult because the resulting products work. In addition, there's several
benefits of conservative language development: it's generally easier to write
compilers; existing programmers will find it easier to adopt a language that
mostly resembles ones they already know; and some unfashionable but useful
features may be retained.

This is more of a "worse is better" situation than a "cargo cult" one.

------
jfarmer
To answer the question, one has to define precisely what "returning multiple
values" should mean.

It's hard to see how this is indistinguishable from returning a
list/array/tuple plus supporting list destructuring syntactically, even in a
limited way. This works in Ruby, for example:

    
    
        name, email = ["Jesse Farmer", "jesse@20bits.com"]
    

So, you can have a function which returns an Array and the caller can "act" as
if it's returning multiple values of mixed types. Python can do the same
thing. Does this count as supporting "multiple return values?"

One might think about this mathematically "as if" returning multiple values
were the (functional) composition of returning a list and list destructuring.
If your language supports lists, you'll always have the ability to return a
list, so in a world where one wants to support returning multiple values, why
add support for it "directly" when you can add support for something simpler
and more broadly applicable and get the same results?

I think that's the practical, language-designy answer. I don't like appealing
to the mathematical definition of a function, since that doesn't account for
languages like Ruby and Python which presumably wouldn't fall into the
original poster's bucket of languages that support "returning multiple
values."

And yet, I could (in principle) return a tuple of a different length each time
I called a function in either language. This means functions in Python and
Ruby are about as far away from the mathematical definition of a function as
one can get, so that couldn't be why they don't support multiple return values
in the sense that the original poster meant.

Lua is one of the few languages I know which differentiates both syntactically
and semantically between "returning a list" and "returning multiple values."

    
    
        function return_multiple()
          return 1,2,3
        end
    
        function return_list()
          return {1,2,3}
        end
    
        a,b,c = return_multiple()
        print(a) -- prints out "1"
    
        a,b,c = return_list()
        print(a) -- prints out, e.g., "table: 0x7fc991500d20"
    

Note that I'm using the word "list" where Lua would use the word "table" and
using the word "multiple return values" where Lua would use the word "list."
That is, in Lua "return 1,2,3" is "returning a list" and "return {1,2,3}" is
"returning a table." However, lists aren't values in Lua, i.e., I can't assign
a Lua-list to a variable and pass it around, so for clarity's sake I'm using
terms that make more sense in non-Lua languages.

The interesting thing about Lua's "multiple return values" is that they almost
behave like splatted lists in Ruby — like a chunk of syntax.

    
    
        function add(a,b)
          return a + b
        end
    
        function return_multiple()
          return 1,2
        end
    
        sum = add(return_multiple())
        -- sum is now 3
        -- add({1,2}) would throw an error, however
    

In Lua, one can use "unpack" to destructure/splat lists like {1,2,3}, so

    
    
        sum = add(unpack({1,2}))
    

would work.

At the end of the day, these approaches all tend to be isomorphic to each
other. Given Lua's design considerations (small, fast, easy to move in and out
of C, etc.) I'm guessing it makes these distinctions for performance/memory
management reasons, but I don't know enough about Lua's internals to say
whether that's the actual justification. Outside of that I think Lua's choices
are strange since you now have functions which don't return _a_ particular
value, but rather these non-syntactic entities called "multiple return
values."

~~~
plorkyeran
Lua's weird return values are basically just exposing the fact that it's a
stack-based VM and letting the user take advantage of that. foo(1,
return_two_values(arg), 2) pushes 1 onto the stack, pushes arg onto the stack,
calls return_two_values (which pops one value from the stack and pushes two
new ones), pushes 2 onto the stack, and then calls foo, resulting in foo being
called with four arguments.

With this design you get zero-overhead (you save the construction of a table)
multiple return values for free, since it simply requires a trivial bit of
syntax and no error checking to verify that a function only left zero or one
values on the stack. Lists aren't exposed as concrete things that can be
passed around because the really aren't things at all.

~~~
anonymoushn
Actually, foo(1, return_two_values(arg), 2) will call foo with only three
values. The , truncates (or extends) the left expression to exactly one value.

    
    
      > return (function() end)(), 5
      nil	5
      > return (function() return 1,2,3,4 end)(), 5
      1	5
      > return 5, (function() end)()
      5
      > return 5, (function() return 1,2,3,4 end)()
      5	1	2	3	4
      > return 5, (function() return nil end)()
      5	nil

------
DougWebb
Perl's context addresses this in a useful way; a function can be called in a
void context (no value expected), a scalar context (one value expected) or a
list context (multiple values expected.) The function can detect which context
it's being called in and alter it's response accordingly.

List context works really well with list assignment, which lets you assign
multiple return values directly to muliple scalar variables. It also works
well with passing multiple return values to the input of another function, of
course.

------
anaphor
Racket can actually return multiple values rather than a product type, which
is what Python does. However people don't usually use it because it's easier
to just return a pair or whatever and then pattern match on it.

[http://docs.racket-lang.org/reference/eval-
model.html#%28par...](http://docs.racket-lang.org/reference/eval-
model.html#%28part._values-model%29)

~~~
derleth
Common Lisp can do the same thing, and people typically prefer returning a
product type because _capturing_ multiple return values invariably introduces
some extra syntax.

Forth functions (or words, if you insist) can return multiple values as easily
as they can return a single value, but the stack metaphor makes this a lot
more natural. This is also true of Joy and RPL and other languages which are
conceptually organized around mutating a (notional) stack. Multiple return
values only become unnatural when you choose an abstraction other than the
stack.

~~~
anaphor
I have used RPL (I have an HP 50G) and yeah, you can do some fun stuff with
the stack. Although I wish they would just port Factor to it already :P

------
com2kid
In low level languages such as C, I imagine it was an attempt to map to the
machines of the day. It isn't hard to come up with an ABI that allows for
returning multiple values, and with registers being thrown into CPUs left and
right now days, using 1 more register to allow two return parameters would
actually be really nice.

(Of course you'd have to dump anything beyond that onto the stack!)

I imagine the world would be a lot different (or at least a bit less buggy!)
if C had allowed for returning an error code in addition to a return value.

Once you get to higher level languages though, the need sort of falls away.
Put data into a container of some type, call it a day.

------
njharman
I use multiple return values in Python all the time. Returning tuples (which
due to multiple assignment actually work / appear as multiple return values).
And using continuations, generator functions, etc.

------
thetwiceler
Perhaps the more interesting question is why do most programming languages
allow several input values?

I'll make the argument that in Haskell, functions BOTH support only a single
input value and a single output value. For example, consider the function (+)
which takes two numbers and returns their sum. The type of (+) is (+) :: Num a
=> a -> (a -> a). I have added the parentheses to emphasize the syntax of the
type. (+) is a function which takes a single number as input and gives a
single function as output!

Now, we can do something like f :: (a,b) -> (x,y,z) and write:

    
    
      let (x0,y0,z0) = f (a0,b0)
    

But this isn't really multiple input or return values. We are just inputting
or returning a struct (with constructor (,) or (,,), respectively), and we can
pattern match against it for the return value.

I think that any elegant language should support as few "primitive features"
as possible - it should be simple, and let a few powerful ideas (e.g., first-
class functions, currying, and pattern matching) let the rest fall out. I
think Haskell really embodies this idea.

~~~
pcwalton
I've thought about switching to only one input value for Rust, but it's needed
for the FFI, so once we're paying the complexity there we might as well pay it
everywhere. Besides, it'll make it easier to add optional and named parameters
if we ever do in the future.

~~~
taliesinb
Wouldn't memory layout on the stack be the same for a tuple vs a sequence of
arguments?

~~~
pcwalton
Unfortunately calling conventions are hideously complex; some arguments go in
registers, some go on the stack, some change depending on whether they're
structs or floats or not…it's a giant mess :(

------
oakwhiz
It seems to me that some domain-specific computations are better modeled with
the ability to return multiple values. For example, digital signal processing
- a handy abstraction in DSP is the idea of having "blocks" and simply
connecting the outputs of some blocks to the inputs of other blocks. A block
in this model can be viewed as a function which is executed continuously.

------
ufmace
I still haven't read a really good reason. I use Ruby for most of my personal
work, which does infact let you return multiple values in a clean and
straightforward way. Though being dynamically typed and not requiring variable
declarations probably helps more with that.

I work mostly in C#, and the lack of multiple return values hits me about once
a month or so, and I usually have to create a new class just for the purpose
of returning two values from one function one time that will never be used
again. There's several other possibilities, most of which are even more
awkward and annoying - out and ref params, which need some variables declared
separately; arrays, lists, and dictionaries, which need either the same type
or casting and index by numbers or a string, and tuples, which have strong
typing, but name everything Item1, Item2, etc. It might be a good solution if
there was support for anonymous functions as return types, but I don't think
you can do that right now without using dynamic.

~~~
djur
Sounds like C# needs destructuring assignment. In Ruby, you're more or less
just returning an array that gets destructured immediately -- "return a, b"
works the same as "return [a, b]".

~~~
ufmace
Yeah, I thought of that. The trouble is, in Ruby, that works nicely as
syntactic sugar because of the dynamically typed nature of the language.
Methods have no declared return types, variables also have no declared types,
arrays and other data structures hold any kind of object, and you can try and
do anything to any variable, and the interpreter will figure out at runtime if
that's possible and throw if it can't do it. When you "return a, b", it's
clearly an array of objects, since that's the only array Ruby has, and it
doesn't matter what the types of a and b are, since the array can hold any
type, and the return type is never declared anyways. When you go to use it,
you can do "a, b = foo()", which is fine, since you don't have to declare
types of variables anyways. You can try and do anything to those a and b after
foo, and the interpreter figures it out at runtime.

In C#, and I expect Java and most other more statically typed languages, you
run into all kinds of awkwardness doing this. Arrays and other data structures
are strongly typed by default, and number and type of method returns must be
declared. You could return a object[], which is easy enough to declare, but
then on the call side, you'd have to declare a object[] to receive the return,
then individually cast each element to whatever type it's supposed to be
before you can do anything with it. Kinda awkward, and against the spirit of
the language.

Declaring multiple returns of different types doesn't seem to help much,
either, since you can't declare 2 variables of different types on the same
line, so you have to declare them both somewhere else, making it about as
awkward as using out params.

The best solution I can think of that fits with the spirit of the language is
to use anonymous types. You can already do:

var something = new { Foo = a, Bar = b }; something.Foo.DoStuff();
something.Bar.DoStuff();

In that case, the compiler creates a class for "something" for you invisibly,
based on the properties you assigned. What's neat about that is that it
maintains strong typing of everything, since it figured out the types from the
declaration, so you can still do things with the Foo and Bar properties, and
it knows what types they are and enforces all of the standard compile-time
type checking.

The downside is that you can't return these anonymous types from a method, as
the method return type must normally be statically declared. You could return
dynamic, but then you lose all of that static type checking, and are back to a
slightly cleaner version of returning object[]. I suppose the language authors
figured that it's too complex to return anonymous types from methods, as far
as figuring out at compile-time what you're actually calling and what it would
return.

And now that I think I've successfully argued myself out of what I originally
wanted to do with a ridiculous number of words, I'll just give up.

------
wreegab
My thought was, values from function calls used to be returned in one
dedicated CPU register (maybe two in some exceptional cases).

------
falcolas
"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."

Python only returns a single value - a tuple. It's just that there is symantic
sugar on the functions side to fold multiple values into a tuple, and on the
side that's returned to, it's simple value unpacking.

You can validate this in the following way:

    
    
        >>> def foo():
        ...     return 1, 2
        >>> x = foo()
        >>> isinstance(x, tuple)
        True
    

The unpacking of tuples into arguments is simply more syntactic sugar, if very
useful syntactic sugar.

In short, while I love Python, it's still returning just a single value - a
tuple, that gives the appearance of returning multiple values.

------
pcwalton
It's pretty simple IMO: supporting multiple return values constitutes
unnecessary language complexity once you have tuples in your language (which
you should, because they are extremely simple and generalize to many other
patterns beyond returning multiple values).

~~~
anonymoushn
Why support multiple arguments?

~~~
informatimago
Indeed.

~~~
pcwalton
In many cases, I do think it's the right decision to only support one argument
per function, but I explained why Rust doesn't do that here:
[https://news.ycombinator.com/item?id=6949077](https://news.ycombinator.com/item?id=6949077)

------
cclogg
This is an interesting question!

I've come across the thought myself from time to time... usually have to end
up creating objects/structs to then return, though in the past when I've been
lazy (on iOS) I've chunked things into NSArray/NSDictionary.

But darn, I can't remember specific examples right now, I know I've definitely
had moments where returning multiple things would have been nice lol.

~~~
krapp
I've found returning type and boolean useful more than once, usually 'data of
type and false if something went wrong or the return data is invalid, data of
type and true if valid.'

std::pair<T, boolean> was like a gift from the gods when I found out about it

------
asmman1
Generalizing, there's really a math relation but it's most because the
language designer wanted this. Nobody wanted to add this feature (not so
trivial to a compiler) if they just could return a struct.

------
pjbrunet
Most? Isn't "pass by reference" a feature of most languages? But yeah
"mathematical constructs" don't most kids learn functions in elementary
school? How is this front page news?

------
lttlrck
Maybe because the dominant use pattern where return cannot be substituted by
output parameters is in expressions. In other words if there were no
expressions then return would not be needed at all.

------
otikik
Because most programming languages are not that good.

