为什么输入此代码
(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:
如果曾经使用proc的continuation参数,那么它将删除当前continuation的一部分,直到使用提示标记标记的最近提示(不包括提示;如果不存在这样的提示,则exn:fail:contract:引发连续异常),....
在您的第一个示例中,当您应用cc
时,在上下文中(“在堆栈上”)没有提示pr
。发生应用程序时],因此会引发异常。
第二个示例有效,因为总是提示您输入默认标签。
第三个示例之所以有效,是因为call-with-composable-continuation
创建的继续过程不会中止当前的继续,因此没有适用其先决条件的条件。 (这就是为什么它被认为是“可组合的”延续的一部分。)
如果有帮助,这是大约
如何根据call/cc
和abort-current-continuation
定义call-with-compposable-continuation
。 (警告:我没有测试过,因此可能存在错误。)在下面的类型注释中,我使用以下约定:P
是与提示标记关联的结果类型,A
是call/cc
或call/comp
调用,这也是延续参数的类型。 ⊥
是空类型;它实际上意味着“不回来”。;; 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/cc
与dynamic-wind
实际交互的方式,不适用于自定义提示处理程序,也不考虑多个返回值(对应于多个连续参数),但是它应该使您大致了解call/cc
的功能。特别地,对abort-current-continuation
的调用要求当前的延续具有标有tag
的提示。