В схеме PLT процедура ошибка вызывает исключение 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-схеме, прочитайте о с обработчиками и dynamic-wind в MzScheme Language Manual Используя их, вы даже можете эмулировать 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 ...)))))