[plt-scheme] Multiple values

From: John Clements (clements at brinckerhoff.org)
Date: Tue Feb 21 12:07:54 EST 2006

On Feb 21, 2006, at 1:43 AM, Adam Wick wrote:

> On Feb 21, 2006, at 2:07 AM, Jim Blandy wrote:
>> But in this case, utility and happiness did not bloom magically into
>> existence through the removal of restrictions, as the Scheme  
>> mythology
>> requires.  It doesn't seem that people generally find multiple value
>> returns very useful.
> Just as a data point, I find multiple value returns very useful, I  
> use them frequently, and they make me very happy.
> The example I use most often involves compiler passes. Many times  
> in a compiler pass, for any particularly expression or statement,  
> how you want to recombine the statement after recursing over the  
> sub-parts depends on additional information about those subparts.  
> For example, what variables they reference, the types of the  
> subexpressions, whether or not one of the subexpressions called  
> setjmp() or call/cc, and so on. Multiple value returns offer a very  
> convenient way to pass the information back up the recursion stack  
> without making the routines go exponential.
> You can, of course, pass the information back in other ways.  
> Passing tuples back certainly works, but it's a pain; you're  
> constantly allocating the tuple to return, immediately splitting it  
> apart and then let-binding it anyways. It makes more sense to me to  
> just return the values directly, and then let-bind them all at once  
> with let-values. CPS works, and it's what I used before I learned  
> the joys of value/let-values, but CPS does bad things to one's  
> stack trace when trying to hunt down errors. Also, as a minor  
> point, at some point with CPS either you begin to fragment your  
> program past sensibility or your indenting just goes insane.

Yes, the stepper has very much the same set of requirements (pass  
over the code, return annotated code plus free vars).

On the other hand, I can't stand the syntax of multiple values.   
First and foremost among these is that you can't treat two values as  
one.  For instance, suppose you want to do a 'map' over a procedure  
that returns two values.  Sorry!

For these reasons, I bit the bullet and adopted the Barzilay-esque  
solution of implementing my own set of macros that simply make it  
easier to pack and unpack vectors of length 2.  I write (2vals a b)  
to build one (it's really just a vector),  and I have a nice  
"let*-2vals" form that can match them or leave them bundled.  E.G.:

(let*-2vals ([(a b) (one-call-that-returns-2-values)]
              [c (another-call-that-returns-2-values)])
   ... body ...)

This way, I can treat them as one value or two, as I please.

The down side, of course, is that anyone reading the code has to go  
through the !@$ phase of deciding what my 2vals macro does.  And, of  
course, it doesn't scale at all.

John "3vals?  What are you, crazy?"  Clements

P.S.: Grr. You said recursing!

Posted on the users mailing list.