如何在 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-continuation
和call-with-compposable-continuation
定义call/cc
。 (警告:我没有对此进行测试,因此可能存在错误。)在下面的类型注释中,我使用以下约定:P
是与提示标记关联的结果类型,A
是call/cc
或 call/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/cc
与 dynamic-wind
的实际交互方式,它不适用于自定义提示处理程序,也没有说明多个 return值(对应于多个连续参数),但它应该让您大致了解 call/cc
在做什么。特别是,对 abort-current-continuation
的调用要求当前延续具有标记为 tag
.
的提示
为什么这个代码
(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-continuation
和call-with-compposable-continuation
定义call/cc
。 (警告:我没有对此进行测试,因此可能存在错误。)在下面的类型注释中,我使用以下约定:P
是与提示标记关联的结果类型,A
是call/cc
或 call/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/cc
与 dynamic-wind
的实际交互方式,它不适用于自定义提示处理程序,也没有说明多个 return值(对应于多个连续参数),但它应该让您大致了解 call/cc
在做什么。特别是,对 abort-current-continuation
的调用要求当前延续具有标记为 tag
.