5

考虑以下代码:

(call-with-values
    (lambda ()
      (call/cc (lambda (k)
         (k k k))))
  (lambda (x y)
    (procedure-arity y)))

这里很明显,call/cc调用点的延续是右侧的 lambda,所以它的 arity 应该是 2。但是,上面的返回值(在 Racket 中)是(arity-at-least 0)相反的。

事实上,在 Guile 中运行类似的代码(代替procedure-minimum-arityprocedure-arity表明延续也应该允许任意数量的参数,即使很明显不是这种情况。

那么,这是为什么呢?据我所知(如果我的理解有误,请纠正我),延续的元数非常简单:它是 1 ,但在 的上下文中除外call-with-values,在这种情况下,无论右侧 lambda 的元数是多少。(当然,如果它是 acase-lambda或类似的,可能会很复杂,但不会比(procedure-arity (case-lambda ...))直接调用更复杂。)

4

1 回答 1

2

一个更简单的查看方法是:

(call-with-values
  (lambda () (error 'arity "~v" (procedure-arity (call/cc (λ (k) k)))))
  (lambda (x y) (procedure-arity y)))

甚至更简单:

(procedure-arity (call/cc (λ (x) x)))

对于你的问题——很明显,在第一种情况下,延续需要两个输入,但这样的情况并不太常见。例如,它们通常是这样的示例,而“真实代码”将使用define-values或具有一些未知的延续,其中call/cc创建的延续可能具有不同的数量,具体取决于它们创建的上下文。这意味着,试图找出这些罕见的情况(其中已知延续的数量)没有多大意义。

脚注:

;; nonsensical, but shows the point
(define (foo) (call/cc (λ (x) x)))
(define x (foo))
(define-values [y z] (foo))
于 2012-07-06T14:01:03.350 回答