如何在 Racket 中使用带有 call/cc 的标记提示?

How to use tagged prompts with call/cc in Racket?

为什么这个代码

(let ([cc #f]
      [pr (make-continuation-prompt-tag 'pr)])
  (call-with-continuation-prompt
   (λ () (displayln
          (+ 2 (call-with-current-continuation
                (λ (k) (set! cc k) 1)
                pr))))
   pr)
  (cc 4))

(在 Racket v7.5 上)引发异常?:

3
; continuation application: no corresponding prompt in the current continuation
; Context:
;  /usr/share/racket/collects/racket/repl.rkt:11:26

虽然带有默认标记的相同代码按预期工作:

(let ([cc #f])
  (call-with-continuation-prompt
   (λ ()
     (displayln (+ 2 (call-with-current-continuation
                      (λ (k) (set! cc k) 1))))))
  (cc 4))
3
6

和具有可组合延续性的相同(与第一个片段)代码

(let ([cc #f]
      [pr (make-continuation-prompt-tag 'pr)])
  (call-with-continuation-prompt
   (λ () (displayln
          (+ 2 (call-with-composable-continuation
                (λ (k) (set! cc k) 1)
                pr))))
   pr)
  (cc 4))

也按预期工作:

3
6

第一个片段有什么问题?还是我理解有问题?

来自 the docs for call-with-current-continuation:

If the continuation argument to proc is ever applied, then it removes the portion of the current continuation up to the nearest prompt tagged by prompt-tag (not including the prompt; if no such prompt exists, the exn:fail:contract:continuation exception is raised), ....

在您的第一个示例中,当您应用 cc 时,上下文中没有提示 pr ("on the stack") 当应用发生时,所以它引发了一个异常。

第二个示例有效,因为总是提示输入默认标签。

第三个示例之所以有效,是因为 call-with-composable-continuation 创建了一个不会中止当前继续的继续过程,因此它的应用没有先决条件。 (这就是为什么它被认为是 "composable" 延续的部分原因。)


如果有帮助,这里是大约如何根据abort-current-continuationcall-with-compposable-continuation定义call/cc。 (警告:我没有对此进行测试,因此可能存在错误。)在下面的类型注释中,我使用以下约定:P 是与提示标记关联的结果类型,Acall/cccall/comp 调用的结果类型,也是延续参数的类型。 为空类型;它实际上意味着 "doesn't return".

;; call-with-continuation-prompt : (-> P) PromptTag[P] -> P
;; Only allows default abort handler!

;; abort-current-continuation : PromptTag[P] (-> P) -> ⊥
;; Assumes the default abort handler!

;; call-with-composable-continuation : ((A -> P) -> A) PromptTag[P] -> A

;; call/cc : ((A -> ⊥) -> A) PromptTag[P] -> A
(define (call/cc proc tag)
  (call-with-composable-continuation
   (lambda (ck) ;; ck : A -> P
     ;; k : A -> ⊥
     (define (k v)
       (abort-current-continuation tag
         (lambda () (ck v))))
     (proc k))
   tag))

此定义没有说明 call/ccdynamic-wind 的实际交互方式,它不适用于自定义提示处理程序,也没有说明多个 return值(对应于多个连续参数),但它应该让您大致了解 call/cc 在做什么。特别是,对 abort-current-continuation 的调用要求当前延续具有标记为 tag.

的提示