rai*_*in1 6 theory scheme continuations exception racket
我无法使用动态范围的变量来实现异常(handle和raise)abort.
这个问题来自阅读论文动态绑定的句法理论,第6节图7.
我所尝试的似乎正常工作,在try块中抛出异常,并在try块内的try块中抛出异常.
什么不能正常工作是从处理程序内部抛出异常.在这种情况下,它应该中止到下一次尝试阻塞.
您可以在球拍计划中看到我的作品,以及2个测试程序.test-1正在运行,test-2正在运行.
#lang racket
;; A Syntactic Theory of Dynamic Binding - Luc Moreau
;; https://link.springer.com/content/pdf/10.1007%2FBFb0030637.pdf
(require racket/control)
(define x_ed (make-parameter 'x_ed))
; NOTE: (abort ..) is the same as (shift k ..) where you don't use k
; NOTE: in (handle f M) we call f the handler and M the try block
; v1
;(define-syntax handle
; (syntax-rules ()
; ((handle f M)
; (parameterize ((x_ed (lambda (v) (abort (f v))))) M))))
; v2
;(define-syntax handle
; (syntax-rules ()
; ((handle f M)
; (reset (parameterize ((x_ed (lambda (v) (abort (f v))))) M)))))
; v3
;(define-syntax handle
; (syntax-rules ()
; ((handle f M)
; (parameterize ((x_ed (lambda (v) (abort (f v))))) (reset M)))))
; v4
(define-syntax handle
(syntax-rules ()
((handle f M)
(let ((old-x_ed (x_ed)))
(parameterize ((x_ed (lambda (v)
(abort (parameterize ((x_ed old-x_ed))
(f v))))))
(reset M))))))
(define-syntax raise
(syntax-rules ()
((raise v) ((x_ed) v))))
(define (print x) (write x) (newline))
(define (test-1)
(print "level-1 open")
(handle (lambda (v)
(print "level-1 caught"))
(begin
(print "level-2 open")
(handle (lambda (v)
(print "level-2 caught"))
(begin
(print "level-3 open")
(raise #t)
(print "level-3 close")))
(print "level-2 close")))
(print "level-1 close"))
(define (test-2)
(print "level-1 open")
(handle (lambda (v)
(print "level-1 caught"))
(begin
(print "level-2 open")
(handle (lambda (v)
(print "level-2 caught")
(raise #t))
(begin
(print "level-3 open")
(raise #t)
(print "level-3 close")))
(print "level-2 close")))
(print "level-1 close"))
;v1
;> (test-1)
;"level-1 open"
;"level-2 open"
;"level-3 open"
;"level-2 caught"
;v2 and v3
;> (test-1)
;"level-1 open"
;"level-2 open"
;"level-3 open"
;"level-2 caught"
;"level-2 close"
;"level-1 close"
;v2 and v3
;> (test-2)
;...
;"level-2 caught"
;"level-2 caught"
; infinite loop
;v4
;> (test-2)
;"level-1 open"
;"level-2 open"
;"level-3 open"
;"level-2 caught"
;"level-1 caught"
;"level-2 close" <--- we don't want this to happen
;"level-1 close"
Run Code Online (Sandbox Code Playgroud)
谢谢.
由于答案,我能够提出这个工作版本:
(define-syntax handle
(syntax-rules ()
((handle f M)
(prompt0
(parameterize ((x_ed (lambda (v)
(control0 k (f v)))))
M)))))
Run Code Online (Sandbox Code Playgroud)
(编辑:我错在使用特殊的控制运算符来实现更节省空间的实现。这可能使处理程序相对于handle表单在尾部位置运行,但是我不知道有什么方法可以评估身体也处于尾部位置。)
首先,您是否专门尝试在就可以通过简单的转义连续性来实现异常处理的更直接方法。handle表单主体相对于handle表单本身处于尾部位置时实施异常处理?如果不是这样,
但是,如果您确实要实现“空间安全”或“适当地尾部递归”异常处理,请继续阅读。
handle以空间安全的方式实现的挑战在于,要避免在“无异常引发”路径中插入额外的堆栈框架,您需要具有展开堆栈并在该上下文中使用表达式恢复计算的能力。或者等效地,通过在该上下文中调用过程来恢复评估。这与所call/cc提供的有所不同;它只允许您展开堆栈,然后立即将一个值返回到该上下文中。
您可以call/cc通过插入额外的堆栈框架(因此主体不在尾部位置)来模拟额外的力量:
;; call/cc : ((Any -> None) -> Any) -> Any
;; call/cc/apply : (((-> Any) -> None) -> Any) -> Any
(define (call/cc/apply proc)
((call/cc (lambda (k) (let ([v (proc k)]) (lambda () v))))))
Run Code Online (Sandbox Code Playgroud)
额外的堆栈框架来自call/cc表达式结果的应用。
您可以消除对额外堆栈框架的需求吗?是! 但不能与shift和reset。
您遇到的问题是(abort e)(abort与Felleisen和Hieb的A运算符相对应)与不相同(shift _ e)。如果查看一下shift和reset的文档,则会看到以下缩减规则:
(reset val) => val
(reset E[(shift k expr)]) => (reset ((lambda (k) expr)
(lambda (v) (reset E[v]))))
; where E has no reset
Run Code Online (Sandbox Code Playgroud)
也就是说,shift不删除其定界符reset,并且这种顽固的行为reset会阻止您从级别2处理程序直接跳到级别1处理程序而无需运行(print "level-2 close")。您需要选择一个定界符和一个允许删除定界符的控制运算符。
您无法使用reset和进行操作shift。
您无法使用prompt和进行操作control。
您可以使用prompt0和进行操作control0。
您可以使用%and fcontrol(以及正确的处理程序)来实现。
当然,您可以使用call-with-continuation-promptand abort-current-continuation(以及正确的处理程序)来完成此操作。