PLTScheme如何捕获错误?

unj*_*nj2 5 scheme continuations racket

我很惊讶PLTScheme中的"错误"功能.如果我有一个除零,它不会做任何其他递归,只是从调用堆栈出来并给我一个错误.

在所有功能之前是否存在隐含的延续?错误是否会丢弃调用堆栈?有没有人对此有任何想法?

Vij*_*hew 6

在PLT Scheme中,过程错误引发异常exn:fail,其中包含错误字符串.所有定义都没有"隐式捕获".请看以下示例:

;; test.ss
(define (a d)
  (printf "~a~n" (/ 10 d)))

(a 0) ;; The interpreter will exit here.     
(printf "OK~n")
Run Code Online (Sandbox Code Playgroud)

从命令行执行上面的脚本,你会看到在打印之后存在解释器

/: division by zero

 === context ===
/home/user/test.ss:1:0: a
Run Code Online (Sandbox Code Playgroud)

如果在用户程序中未处理异常,则会将其传播到核心解释器,默认处理程序处理该异常,即打印异常并退出.换句话说,翻译只是说,"提出了一个例外,我不知道如何处理它,所以我退出了".这与JVM或其他虚拟机处理异常的方式没有太大区别.

要了解有关PLT Scheme的异常处理机制的更多信息,请阅读MzScheme语言手册中的with-handlersdynamic-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))))))
Run Code Online (Sandbox Code Playgroud)

以下是使上述成为可能的语法扩展:

;; 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 ...)))))
Run Code Online (Sandbox Code Playgroud)