Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Racket 如何解释球拍中call/cc的有趣行为?_Racket - Fatal编程技术网

Racket 如何解释球拍中call/cc的有趣行为?

Racket 如何解释球拍中call/cc的有趣行为?,racket,Racket,联合收割机必须使用二进制运算符bin映射reduce列表,但如果发现任何值不符合谓词pred?,则必须返回exc,如果发现任何此类值,则不得对列表执行任何计算 这是一个简单的延拓问题 #lang racket (define (id x) x) (define (const x) (lambda (_) x)) (define (combine pred? bin zero exc) (call/cc (lambda (exit) (letrec

联合收割机必须使用二进制运算符bin映射reduce列表,但如果发现任何值不符合谓词pred?,则必须返回exc,如果发现任何此类值,则不得对列表执行任何计算

这是一个简单的延拓问题

#lang racket

(define (id x)
  x)

(define (const x)
  (lambda (_) x))

(define (combine pred? bin zero exc)
  (call/cc
   (lambda (exit)
     (letrec
         ((f (lambda (xs)
               (if (empty? xs)
                   zero
                   (if (pred? (first xs))
                       (exit exc)
                       (bin (first xs) (f (rest xs))))))))
       f))))

(define product
  (combine zero?
           *
           1
           0))

(product '(1 2 3 0 4))
代码几乎可以工作,但有一个非常微妙的错误

它引发了以下异常:

define-values: assignment disallowed;
 cannot re-define a constant
  constant: product
让它工作起来很容易。只需要一点小小的改变:

(define (combine pred? bin un zero exc)
  (lambda (ys)
    (call/cc
     (lambda (exit)
       (letrec
           ((f (lambda (xs)
                 (if (empty? xs)
                     zero
                     (if (pred? (first xs))
                         (exit exc)
                         (bin (first xs) (f (rest xs))))))))
         (f ys))))))

我知道问题在于,Racket,define的延续,是为了定义一个函数,但是有人能给出更多的细节吗?例如,涉及哪些语法转换?

思考一下您在这里必须遵循的顺序:

(define product (combine ....))
在这里,您首先评估联合收割机。。。而continuation是程序的其余部分,首先将计算值存储为名称乘积。从withing f调用continuation将直接返回到重新存储产品

通过调用产品“1 2 3 0 4”,您正在重新定义产品,因为它是程序的延续,call/cc捕获延续


在第二次尝试中,您进行了真正的重构,将其包装在lambda中,并使用相同的参数调用f。它只是延迟调用/抄送发生的时间,从而延迟继续中包含的内容。在这个版本中,延续是产品之后的任何内容。。。而不是定义产品中的产品设置…

这可以用方案本身来解释,还是在实现中我们必须看语言之外的东西?@Rdgstv lang racket不遵循标准,但它似乎符合!r6rs报告:实现职责:实现应检测到的延续被多次调用。如果实现检测到这一点,它必须使用条件类型和断言引发异常。。Racket实现支持许多标准方案报告语言。我已经看到许多已经定义和设置的scheme实现!与原语相同。@Rdgstv理解call/cc。call/cc所做的就是将continuation作为函数公开。不管怎样,许多Scheme实现都会将代码转换为CPS,但那些不这样做的人会将代码转换为call/cc。CPS调用/cc只是定义调用/cc主体c主体lambda值实际延续c值c。像define这样的特殊形式在CPS中很难实现,因为我们没有从函数中定义顶级绑定的原语。函数内部的define变成了一个letrec,这不是我们想要的