[plt-scheme] Multiple values

From: hufflen jean-michel (hufflen at lifc.univ-fcomte.fr)
Date: Tue Feb 21 10:36:43 EST 2006

>From plt-scheme-bounces at list.cs.brown.edu  Tue Feb 21 10:42:15 2006
>(...)

   Whow!  When I asked you for my first question, I did not know that this 
will cause such a discussion!

   BTW, I agree with:

>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. (...)

   In addition, my opinion is that multiple values allows us to think about
producer/consumer, in a nicer way than CPS.  If we consider the example I
already gave:

(define (butlast-and-last l)
  (let ((first (car l))
        (rest (cdr l)))
    (if (null? rest)
        (values '() first)
        (call-with-values (lambda () (butlast-and-last rest))
          (lambda (l0 last-0) (values (cons first l0) last-0))))))

it is very close to the same function using CPS, with a 2-argument
continuation:

(define (butlast-and-last-cps l k2)
  (let ((first (car l))
        (rest (cdr l)))
    (if (null? rest)
        (k2 '() first)
        (butlast-and-last-cps rest (lambda (l0 last-0)
                                     (k2 (cons first l0) last-0))))))

In fact, if I write "(values x y)", I think that the 2 values "x" and "y" will
be consumed later. If the "values" function is implemented by:

(define (values . arg-list)
  (lambda (f) (apply f arg-list)))

this can mean that "arg-list" will be consumed later, when the formal argument
"f" is replaced by an "actual" function.  This consumption is explicit in CPS,
implicit with multiple values.  And "call-with-values", from my point of view,
is a bridge between a producer and consumer.

   Back to my question about PLT Scheme's behaviour, I was surprised because I
thought that values' result may be viewed as a whole, that is, as a kind of
"packaged values" to be consumed later.

   Yours sincerely,

			       J.-M. H.


Posted on the users mailing list.