我对 PLTScheme 中的“错误”功能感到惊讶。如果我除以零,它不会进行任何其他递归,只是从调用堆栈中出来并给我一个错误。
在所有功能之前是否有隐含的延续?错误会丢弃调用堆栈吗?有人对此有任何想法吗?
我对 PLTScheme 中的“错误”功能感到惊讶。如果我除以零,它不会进行任何其他递归,只是从调用堆栈中出来并给我一个错误。
在所有功能之前是否有隐含的延续?错误会丢弃调用堆栈吗?有人对此有任何想法吗?
在 PLT Scheme 中,过程错误引发异常exn:fail,其中包含错误字符串。所有定义都没有“隐式捕获”。请看以下示例:
;; test.ss
(define (a d)
(printf "~a~n" (/ 10 d)))
(a 0) ;; The interpreter will exit here.
(printf "OK~n")
从命令行执行上面的脚本,你会在打印类似的东西后看到解释器存在
/: division by zero
=== context ===
/home/user/test.ss:1:0: a
如果在用户程序中没有处理异常,它会传播到核心解释器,由默认处理程序处理它,即打印异常并退出。换句话说,解释器只是说,“引发了异常,我不知道如何处理,所以我退出了”。这与 JVM 或其他一些虚拟机处理异常的方式没有太大区别。
要了解有关 PLT Scheme 的异常处理机制的更多信息,请阅读MzScheme 语言手册中的with-handlers和dynamic-wind。使用这些,您甚至可以模拟 Java 的 try-catch-finally 块。
(define (d a b)
(try
(printf "~a~n" (/ a b))
(catch (lambda (ex)
(printf "Error: ~a" ex)))
(finally
(if (> b -2)
(d a (sub1 b))))))
这是使上述成为可能的语法扩展:
;; try-catch-finally on top of with-handlers and dynamic-wind.
(define-syntax try
(syntax-rules (catch finally)
((_ try-body ... (catch catch-proc))
(with-handlers (((lambda (ex) #t)
(lambda (ex)
(catch-proc ex))))
(begin
try-body ...)))
((_ try-body ... (catch catch-proc) (finally fin-body ...))
(dynamic-wind
(lambda () ())
(lambda ()
(with-handlers (((lambda (ex) #t)
(lambda (ex)
(catch-proc ex))))
(begin
try-body ...)))
(lambda () fin-body ...)))
((_ try-body ... (finally fin-body ...))
(dynamic-wind
(lambda () ())
(lambda () try-body ...)
(lambda () fin-body ...)))))