Re: Multiple return values

Craig Burley <>
22 Apr 1997 21:25:45 -0400

          From comp.compilers

Related articles
[12 earlier articles]
Re: Multiple return values (1997-04-20)
Re: Multiple return values (1997-04-20)
Re: Multiple return values (1997-04-22)
Re: Multiple return values (1997-04-22)
Re: Multiple return values (1997-04-22)
Re: Multiple return values (Mike Ashley) (1997-04-22)
Re: Multiple return values (Craig Burley) (1997-04-22)
Re: Multiple return values (1997-04-22)
Re: Multiple return values (1997-04-30)
Re: Multiple return values (John Haxby) (1997-05-04)
Re: Multiple return values (Jan Galkowski) (1997-05-04)
Re: Multiple return values (1997-05-04)
Re: Multiple return values (1997-05-04)
[11 later articles]
| List of all articles for this month |

From: Craig Burley <>
Newsgroups: comp.compilers,comp.lang.misc
Date: 22 Apr 1997 21:25:45 -0400
Organization: Cygnus Support
References: 97-04-091 97-04-109 97-04-128
Keywords: design, syntax

Our Moderator comments on:

> > (x, y) = foo(a, b);
> >
> > in C you can write
> >
> > foo(a, b, &x, &y);
> [They're different, but I don't think the issues are very different.
> Consider something like (y, x) = foo(x, y), where x and y may be
> passed by reference. -John]

I think there's at least one important distinction here, two if you
simply disallow the concept of "passed by reference" as an important
side-benefit of allowing multiple return values.

`(x, y) = foo(a, b)' and `(y, x) = foo(x, y)' both express quite
clearly and elegantly that foo is to be invoked with the values
represented by the arguments ((a,b) or (x,y)), and that the two
results calculated and returned by foo are to be stored in x and y.

`foo(a, b, &x, &y)' expresses only that the values in a and b, plus
pointers to the memory locations for x and y, are to be passed to foo.
(And, if you think in C++, the first part isn't even what is being
expressed -- the values in a and b might not be passed (?), and/or a and
b might be different upon return, if foo has been defined to accept
these arguments by reference.)

With the former example, the reader _knows_ that x and y _will_ be
written by the statement, that these writes will _not_ interact
"surprisingly" with any reads that happen during evaluation of the
right-hand-side of the assignment, that a and b will _not_ be quietly
modified at some arbitrary point _following_ the assignment, and, if
pass-by-reference isn't allowed, that a and b will not be modified
_during_ the assignment (including during the evaluation of the

That's a lot of useful semantic information, in the sense that it's
useful to a person trying to read, maintain, and debug the code.
(Whether it's useful to a compiler is less important, IMO.)

With the latter example, the reader doesn't know whether x and y need
to even _have_ defined values before the foo() call, whether they'll
be modified _during_ the call, whether they'll be quietly modified
_after_ the call (by foo storing away the pointers to x and y and some
"relative" of foo storing through those saved pointers later), and, if
pass-by-reference _is_ allowed (C++), even whether a and b will be
modified during the call!!

That's a lot of important semantic information that is _missing_ from
that, and many, calls done in C (and C++, which worsens the

The differences are very important not so much for compilers (which us
compiler jocks think we can make smart enough to figure out what
really is going on so as to produce optimal code), but for programmers
who are reading/writing the code.

The semantic advantages of proper return of multiple values are
substantial _assuming_ you take the opportunity to restrict the
language by disallowing things like silent pass-by-reference, which
often aren't really needed semantically except to effect
multiple-value return and to effect optimisation (which we compiler
folk claim we can make happen anyway).

So, yes, you don't necessarily gain any significant _implementation_
advantages by providing multiple return values in a language, but you
can gain some, and if you're smart gain several important, _semantic_
advantages by doing so. (If you care only about implementation stuff
-- e.g. if you can't get out of the rut of saying/thinking "but the
_compiler_ can see that..." -- then stop thinking of yourself as
designing a language, because you're just designing a tool with a
poorly-engineered interface, like C++. Good computer-language design
is the "ergonomic engineering" for the programming community. We all
know plenty of cases where excellent work was accomplished using
working environments with bad ergonomics, so I'm not slamming C++ as
an effective tool in any way. Heck, I use C all the time, still.)
James Craig Burley, Software Craftsperson
[I entirely agree; I meant that the implementation issues weren't very
different. But these days I write everything in perl so that rather than
returning wimpy little tuples, I return hash tables of references. -John]


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.