【问题标题】:How to implement call-with-values to match the values example in R5RS如何实现 call-with-values 以匹配 R5RS 中的值示例
【发布时间】:2013-05-16 11:14:59
【问题描述】:

R5RS 说...

值可能定义如下:

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

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

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

【问题讨论】:

    标签: scheme r5rs


    【解决方案1】:

    Kent Dybvig 定义了 call/cc、values 和 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))))))
    

    【讨论】:

    • 这是一个很好的答案,因为它满足了为缺少它们的实现实现值和调用值的需要。我真的希望有一个与 R5RS 中的值示例兼容的值调用实现,或者解释为什么它不能完成。
    • 为什么包括call/cc?如果没有这个 call/cc,这些版本的值和 call-with-values 是否可以工作?
    • 阅读 Dybvig 原文的链接(关于“thusly”这个词);我所做的只是复制它。但我很确定答案是否定的。
    【解决方案2】:

    简短的回答是:你不能

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

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

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

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

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

    【讨论】:

    • 您提供的基于列表的版本正是我使用的。应该注意的是,除了优化差异之外,值的“真实”实现可以用作标识函数,但这种解决方法会破坏它。 (实际上我在使用的代码中遇到了这个问题。)
    • @RobertFisher 通过使用 Kent Dybvig 的魔术令牌技巧,您可以将其用作身份。 RnRS 规范(也)适用于实施者,因此在我看来这是一个实施提示。我想 (fun a) => b 就在 apply 之前会有 a,fun on stack 在应用之前和 b,continuation 之后在完全 CPS ed 的方案中。
    猜你喜欢
    • 1970-01-01
    • 2018-05-31
    • 2022-08-15
    • 2014-07-28
    • 2017-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多