考虑以下代码:

(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)表明,延续显然也允许任何数量的参数,即使显然不是这种情况。

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

最佳答案

看到相同结果的一种更简单的方法是:

(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))

关于scheme - 为什么延续没有有用的工具?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11339541/

10-12 20:41