3

R5RS 说……

值可能定义如下:

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

然而,它并没有说明如果以这种方式实现值,那么如何实现 call-with-values。那么,如果以这种方式实现值,将如何实现 call-with-values 呢?

(出现这种情况是因为我试图让一些使用带值调用的代码与不支持它的 TinyScheme 一起工作。我通过伪造值和带列表的带值调用来管理,但是——当我看到这在 R5RS 中——我想知道这是否是一个更好的解决方法。)

4

2 回答 2

3

Kent Dybvig定义call/ccvalues因此:call-with-values

(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))))))
于 2013-05-21T18:17:49.253 回答
1

简短的回答是:你不能

漂亮的值实现并没有改变这样一个事实,即如果您没有任何其他过程可以戳这些值,则无法实现其他过程。如果你有一种方法可以窥视,那么你可以用它来实现其他方法。

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

不起作用,这就是为什么你需要那些其他原语。

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

(define values list)
(define (call-with-values producer consumer)
  (apply consumer (producer)))
于 2013-05-26T00:58:14.827 回答