felix <felix@anu.ie> wrote:
+---------------
| Without low-level support multiple values can not be implemented completely.
+---------------
I think I disagree. I think it *can* be implemented completely, though not
particularly efficiently. Granted, the naive student version:
> (define values list)
> (define (call-with-values producer consumer)
(apply consumer (producer)))
> (call-with-values (lambda () (values 4 5))
(lambda (a b) (* a b)))
==> 20
>
*almost* works, as you see, but unfortunately the "producer" thunk is
not required to use "values" to return its result. (Oops!) Specifically,
in R5RS there's this example, which fails with the above:
> (call-with-values * -)
apply: expects type <proper list> as 2nd argument, given: 1
>
But all is not lost. The following somewhat uglier hack suffices, I think:
> (define values 'not-yet)
> (define call-with-values 'not-yet)
> (let ((magic (cons #f #f)))
(set! values
(lambda vals (cons magic vals)))
(set! call-with-values
(lambda (producer consumer)
(let ((v (producer)))
(if (and (pair? v) (eq? (car v) magic))
(apply consumer (cdr v))
(consumer v))))))
and seems to work:
> (call-with-values (lambda () (values 4 5))
(lambda (a b) (* a b)))
==> 20
> (call-with-values * -)
==> -1
>
-Rob
-----
Rob Warnock, 41L-955 rpw3@sgi.com
Applied Networking http://reality.sgi.com/rpw3/
Silicon Graphics, Inc. Phone: 650-933-1673
1600 Amphitheatre Pkwy. PP-ASEL-IA
Mountain View, CA 94043