请考虑以下代码:
(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-arity
代替procedure-arity
)表明延续也可以允许任意数量的参数,即使很明显不是这样。
那么,为什么呢?据我所知(如果我的理解是错误的,请纠正我),延续的优点非常简单:除了call-with-values
的上下文之外它是1,在这种情况下,无论右手的是什么 - 边lambda是。 (如果它是case-lambda
之类的话,授予可能会很复杂,但不会比直接调用(procedure-arity (case-lambda ...))
更复杂。)
答案 0 :(得分: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))