🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.misc
Article #350

Re: Language Tenets (too long)

#350
From: Peter Schachte
Date: Wed, 26 Jul 1989 23:32
98 lines
5034 bytes
In article <1989Jul17.184707.415@maths.nott.ac.uk> anw@maths.nott.ac.uk (Dr A. N. Walker) writes:
> I might want to write
>		records[i++] errcount <- write(fd,buf,BIGBSIZE)/BSIZE
>after which
>		records[i++] = write(fd,buf,BIGBSIZE)/BSIZE;
>		errcount = write(fd,buf,BIGBSIZE)%BSIZE;
>is erroneous and
>		{ int temp = write(fd,buf,BIGBSIZE);
>		  records[i++] = temp / BSIZE;
>		  errcount = temp % BSIZE; }
>is becoming gross (and much harder to optimise).

Absolutely.  But how about:

	    divrem(write(fd,buf,BIGBSIZE), BSIZE, &records[i++], &errcount);

It is essentially the same as your multiple return example, and doesn't
have the same perils.  It does have the flaw that errcount can't be a
register variable.  It is conceivable, though, that a global optimizer
could put errcount into a register.

The problem with multiple returns is filling out the semantics.  As I
see it, there are two basic ways to handle this:

	1.  multiple results are packed up into a single structure to be
	    returned.  To complete the semantics of this, you only need
	    to specify the semantics of passing such a structure as
	    argument to a function (or primitive like +).  One sensible
	    solution is to consider the first of the multiple results to
	    be passed as argument, and the remaining results to be
	    "passed around" the function.  For example, if /% returns a
	    quotient and remainder as values, and + returns one value,
	    then:

		    (x/%y)+z

	    would return two values:  x/y+z and x%y.  I think this
	    semantics could be made to work.

	    I don't really think it's very useful, though.  The problem
	    is that usually, when you have multiple results, you want to
	    do different things with them.  In order to do that with
	    this sort of multiple values, you have to assign them to
	    separate variables.  If you're going to do that anyway, why
	    not just write functions that take pointers indicating where
	    to store the results, as I showed above?

	2.  The other approach is to treat multiple results as separate
	    things.  Forth, Pop-2, and CommonLisp do this.  Forth and
	    Pop-2 store results, as well as arguments, on a stack.  This
	    gives them great flexibility with multiple results; in
	    effect, multiple results are handled just like a single
	    result.  CommonLisp is a bit less flexible*.

	    I am a bit skeptical of Pop-2's approach:

		    foo(divrem(x,y))

	    (where divrem returns both quotient and remainder, and foo
	    takes two arguments) calls foo with x/y and x%m as its two
	    arguments.  It may be pure prejudice, but I'm uncomfortable
	    having two arguments to a function come from the same
	    expression.  In any case, it's not terribly useful, since
	    there's a good chance I'll want the arguments in the other
	    order, or I'll want another argument between them, or
	    something.  I belive Pop-2 does provide stack manipulation
	    primitives, so this can be handled, but it's going to look
	    pretty grungy.  (The same arguments apply to Forth, except
	    that Forth doesn't have the expression notation.  This sort
	    of thing is the way one programs in Forth, so this kind of
	    code looks no different than any other Forth code.)


It seems to me that the cleanest way to handle multiple results is to
just always put them into variables.  And this is better done by passing
pointers to where to put the results than by muddling the semantics of
expressions with multiple returns.  Or alternatively, go to a pure stack
dicipline, where you always manipulate the stack to get the result(s)
from some invocations into others.

----------------
* CommonLisp has 5 forms for handling multiple returns, but none of them
allow you to get multiple results from one function call into different
function calls without putting them into variables first.  For example,
suppose CommonLisp had a divrem function, and suppose I wanted to
compute x/y*10+log(x%y).  I don't see how to do this conveniently without
putting x/y and x%y into temporary variables.  Maybe I'm just missing
it.

This is not a condemnation of CommonLisp.  Since CommonLisp does not
have VAR parameters (to functions) like Pascal or an address-of operator
like C, returning multiple values and putting them into variables is the
most sensible way to handle multiple returns.

-- 
-Peter Schachte
pds@quintus.uucp
...!sun!quintus!pds
Technical Details
Message-ID: <1223@quintus.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!apple!sun-barr!newstop!sun!quintus!pds
References: <57125@linus.UUCP> <1989Jun24.230056.27774@utzoo.uucp> <1207@quintus.UUCP> <1406@l.cc.purdue.edu> <1989Jul17.184707.415@maths.nott.ac.uk>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!apple!sun-barr!newstop!sun!quintus!pds
From: pds@quintus.UUCP (Peter Schachte)
Newsgroups: comp.lang.misc
Subject: Re: Language Tenets (too long)
Message-ID: <1223@quintus.UUCP>
Date: 26 Jul 89 23:32:56 GMT
References: <57125@linus.UUCP> <1989Jun24.230056.27774@utzoo.uucp> <1207@quintus.UUCP> <1406@l.cc.purdue.edu> <1989Jul17.184707.415@maths.nott.ac.uk>
Reply-To: pds@quintus.UUCP (Peter Schachte)
Organization: Quintus Computer Systems, Inc.
Lines: 98