Как PLTScheme перехватывает ошибки?
-
21-09-2019 - |
Вопрос
Я поражен функцией «ошибка» в PLTScheme.Если у меня есть деление на ноль, оно не выполняет никакой другой рекурсии, а просто выходит из стека вызовов и выдает мне ошибку.
Есть ли неявное продолжение перед всеми функциями?Ошибка выбрасывает стек вызовов?Есть ли у кого-нибудь идеи по этому поводу?
Решение
В схеме PLT процедура ошибка вызывает исключение пример: провал, который содержит строку ошибки.Для всех определений не существует «неявного улова».Посмотрите на следующий образец:
;; 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.Используя их, вы даже можете эмулировать блок 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 ...)))))