第11章 异常和状况
异常(exceptions)和状况(conditions)为系统和用户代码提供了发送信号、检测和从错误中恢复程序的方法。
标准语法形式和过程在一些情况下会引发异常,例如,当向过程传递错误数量的参数时,传递给eval
的表达式的语法不正确,或者一个打开文件的过程无法打开文件时。在这些情况下,使用标准的状况类型引发异常。
用户代码也可以通过raise
和raise-continuable
过程来引发异常。在这种情况下,可以使用标准的状况类型,用户定义的标准状况类型的子类型(可以通过define-condition-type
来定义),或者是状况类型之外的任意Scheme值。
在程序执行期间的任何时候,单个异常处理程序(称为current exception handler
)负责处理所有引发的异常。默认情况下,当前异常处理程序通常会打印一条消息,该消息描述引发异常的状况或其它值,对于任何严重的状况,都会终止正在运行的程序。在交互式系统中,这通常意味着重置REPL(“读取-求值-打印 循环”)。
用户代码可以通过guard
语法或with-exception-handler
过程建立新的当前异常处理程序。在任何一种情况下,用户代码都可以处理所有异常,或者,基于引发异常的状况或其他值,只有一些异常,同时重新引用其他异常处理旧的当前异常处理程序。当动态嵌套保护形式和异常处理程序调用时,会建立一系列异常处理程序,每个异常处理程序都可以遵循链中的下一个。
1 引发和处理异常
procedure: (raise obj)
procedure: (raise-continuable obj)
returns: see below
libraries: (rnrs exceptions), (rnrs)
(raise
(condition
(make-error)
(make-message-condition "no go"))) ; --> error: no go
(raise-continuable
(condition
(make-violation)
(make-message-condition "oops"))) ; --> violation: oops
(list
(call/cc
(lambda (k)
(vector
(with-exception-handler
(lambda (x) (k (+ x 5)))
(lambda () (+ (raise 17) 8))))))) ; --> (22)
(list
(vector
(with-exception-handler
(lambda (x) (+ x 5))
(lambda () (+ (raise-continuable 17) 8))))) ; --> (#(30))
(list
(vector
(with-exception-handler
(lambda (x) (+ x 5))
(lambda () (+ (raise 17) 8))))) ; --> violation: non-continuable