[plt-scheme] passing multiple "values" between functions

From: Neil Van Dyke (neil at neilvandyke.org)
Date: Mon Apr 6 04:09:36 EDT 2009

Martin DeMello wrote at 04/06/2009 03:23 AM:
> that there is no "values" object that you can pass around till you're
> ready to unpack it.

Correct.  You can put multiple values into a list, vector, struct, or 
whatever, to aggregate multiple values into a single value, of course.  
But "values" creates truly separate values, not a single value like an 

>  Do values offer any advantage over using lists and
> let-match?

Absolutely.  They are especially useful when writing pure functional 
algorithms, such as when you have an "if" and each branch produces more 
than one value.  You will encounter such situations when you avoid using 
"set!".  It's quite elegant once you get the hang of it.  The only 
inelegant part is syntactic: "let-values" has too long a name and too 
many parentheses.

Multiple values are also convenient when implementing a function that 
"naturally" produces multiple values.  In many other languages, you'd 
probably end up defining a new record type just to package up the return 
values of that particular function, or you'd return an ordered 
collection of the values and then have to destructure it.

Incidentally, there is an arguable incongruity in the multiple-values 
support in Scheme, in that, if "foo" produces 2 values, and "bar" has 
two arguments, you can't just do "(bar (foo))".  As a 4am amusement, I 
kludged up a new application syntax that does support this, though I 
strongly discourage using it.

#lang scheme/base

(define-syntax app
  (syntax-rules ()
    ((_ PROC)         (PROC))
    ((_ PROC ARG ...) (%app:1 (ARG ...) () (PROC)))))
(define-syntax %app:1
  (syntax-rules ()
    ((_ () (BIND ...) (PROC VAR ...))
     (let (BIND ...)
       (apply PROC (append VAR ...))))
    ((_ (ARG0 ARG1 ...) (BIND ...) (PROC VAR ...))
     (%app:1 (ARG1 ...)
             (BIND ... (actual (call-with-values (lambda () ARG0) list)))
             (PROC VAR ... actual)))))

(app vector 1 (values 2 3) 4 (list 5) (values 6 7))
;;==> #(1 2 3 4 (5) 6 7)


Posted on the users mailing list.