[plt-scheme] passing multiple "values" between functions
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
object.
> 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)
--
http://www.neilvandyke.org/