如何实现call-with-values以匹配R5RS中的值示例

时间:2013-05-21 15:49:36

标签: scheme r5rs

R5RS说......

  

值可能定义如下:

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

但是,它没有说明如果以这种方式实现值,如何实现call-with-values。那么,如果以这种方式实现值,那么如何实现call-with-values?

(这是因为我试图获得一些使用call-with-values来处理TinyScheme的代码,它不支持它。我通过伪造值和使用列表调用值来管理,但是 - 当我在R5RS中看到这个时 - 我想知道这是否是一个更好的解决方法。)

2 个答案:

答案 0 :(得分:3)

Kent Dybvig定义call/ccvaluescall-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))))))

答案 1 :(得分:1)

简短的回答是:你不能

值的漂亮实现并没有改变这样一个事实,即如果你没有任何方法可以实现其他程序,那么它们就无法实现其他程序。如果你有一种方法可以窥视,那么你可以用其他方式实现其他方法。

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

不起作用,这就是你需要那些其他原语的原因。

当说的时候。返回更多值和返回列表与值之间没有区别,因为区别在于优化。您可以创建一个将它们都视为绑定的宏,然后您使用它们的方式将是相同的。性能上的差异是一些指针跳跃和一些消耗,这对于任何lisp实现都是合理的。如果你的代码是正确的,那么这将是一个简单的实现:

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