Question

R5RS says...

Values might be defined as follows:

(define (values . things)
  (call-with-current-continuation
    (lambda (cont) (apply cont things))))

It doesn’t, however, say how call-with-values might be implemented if values were implemented this way. So, if values is implemented this way, how would call-with-values be implemented?

(This came up because I was trying to get some code that used call-with-values to work with TinyScheme, which doesn’t support it. I managed by faking values and call-with-values with lists, but—when I saw this in R5RS—I wanted to know if this might be a better workaround.)

Was it helpful?

Solution 2

The short answer is: You can't

The nifty implementation of values does not change the fact that there is no way to implement the other procedures if you don't have any of them to poke at the values. If you had one way to peek then you could implement the others with that.

(+ (values 4 5))
(apply + (values 4 5))

Doesn't work and that's why you need those other primitives.

When that said. There is no difference between returning more values and returning lists with values since the difference is optimization. You could make a macro that treats both of them as a binding and then the way you use them would be the same. The difference in performance is some pointer jumping and some consing which is reasonable fast for any lisp implementation. Heres a minimalistic implementation that will work given your code is correct:

(define values list)
(define (call-with-values producer consumer)
  (apply consumer (producer)))

OTHER TIPS

Kent Dybvig defines call/cc, values and call-with-values thusly:

(define call/cc call/cc)
(define values #f)
(define call-with-values #f)
(let ((magic (cons 'multiple 'values)))
  (define magic?
    (lambda (x)
      (and (pair? x) (eq? (car x) magic)))) 

  (set! call/cc
    (let ((primitive-call/cc call/cc))
      (lambda (p)
        (primitive-call/cc
          (lambda (k)
            (p (lambda args
                 (k (apply values args))))))))) 

  (set! values
    (lambda args
      (if (and (not (null? args)) (null? (cdr args)))
          (car args)
          (cons magic args)))) 

  (set! call-with-values
    (lambda (producer consumer)
      (let ((x (producer)))
        (if (magic? x)
            (apply consumer (cdr x))
            (consumer x))))))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top